Showcasing Kotlin with Complex Numbers and Polynomials — Part I

Dimitri Papaioannou
Sep 5, 2020 · 3 min read

When I first encountered Kotlin, I was excited that it was completely inter-operable with Java and it supported operator overloading. Operator overloading is essential in making a language more palatable to a programmer implementing mathematical operations.

Consider for example, this simple equation in Java

Even such a small equation looks awkward and confusing. What we really want to say, and see is:

My first impulse was to write a library for complex arithmetic in Kotlin and in the process of doing so, I discovered other cool Kotlin features, like extensions, destructuring, and infix notation, which I can exploit to write complex arithmetic expressions almost as if I were writing them on paper.

There are of course already abundant complex libraries in all languages. My objective was not to re-invent the wheel, but to make the writing of arithmetic operations intuitively obvious. The following snippets of code are equivalent:

Complex c = new Complex(1, -1).times(new Complex(0, 2).minus(new Complex(1, 0)));--------------------------------------------------------------------val c = (1-i)*(2*i-1)

but the second is much easier to read.

The first step is to define the Complex class and overload the arithmetic operators.

That’s a good start. Now I can write expression such as this:

It’s not quite perfect yet. The Complex constructor is a bit awkward. Also, whereas we can write expressions like c1*2 and c1*3.5 we cannot write 2*c1 and 3.5*c1, since Complex knows how to multiply itself with Number, but not vice versa.

What we really like to have is something like this: val c1 = 2.0–3.1*i

First, let’s make Kotlin understand what i means¹. This is simple. We can introduce the global (well, package-specific) declaration:

val i = Complex(0.0, 1.0)

Now we need to make expression like this make sense: c1 = 2*c2.

That’s where Kotlin’s extension functions come in handy. These allow you to define functions on a pre-existing class without actually extending the class. For example, if I want a function isEven() on BigInteger, I can do it like this:

fun BigInteger.isEven() : Boolean {
return this.toInt() % 2 == 0
}

or even more compactly:

fun BigInteger.isEven() = this.toInt() % 2 == 0

We can also extend operators:

Now we are cooking. Instead of declaring a complex number with

val c = Complex(1, 0.5)

I can write it out as

val c = 1.0 + 0.5 * i

and I can defined arithmetic expressions that look pretty natural:

val c1 = PI * i
val c2 = (2 - 5*i)/ c1

To get the real and imaginary parts of a complex number c, I can just say c.real and c.img or use Kotlin’s destructuring capability to get them in a pair:

val (x, y) = Complex(1, 2)
assertEquals(1.0, x)
assertEquals(2.0, y)

Defining the standard functions for complex numbers, such as exponential, trig, hyperbolic, et cetera, is pretty straightforward. I had some trouble finding a natural way to denote powers. Most languages, including Kotlin, do not support superscripts, so we can’t have c². The next best thing, c^ 2, is also not possible. However, I was able to use Kotlin’s infix notation to come up with that

val cSquare = c to 2

Here is the implementation

Note that I used an optimization for integer powers to compute it in log(n) time instead of linear.

In the second part of this article, I will describe how I used the same concepts to implement arithmetic operations for complex polynomials.

The complete code for this project can be found in the github repository.

¹ Mathematicians and Physicists use i to denote the imaginary unit. Engineers use j because to them i can only stand for electric current. Physicists use j for current. I chose to use i because I want to reserve j and k for implementing Quaternions.

Software Science

Math + Data + Computer Science = Sotware Science

Dimitri Papaioannou

Written by

I am a software engineer and applied mathematician. My passion is to develop solution in the intersection of software and mathematics.

Software Science

Musings on Math, Data Science, and Sotware Engineering

Dimitri Papaioannou

Written by

I am a software engineer and applied mathematician. My passion is to develop solution in the intersection of software and mathematics.

Software Science

Musings on Math, Data Science, and Sotware Engineering

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store