Skip to the content of the web site.

C++ Complex Numbers, Quaternions, Octonions, Sedenions, etc.

These pages document a C++ implementation of extensions of the real numbers, including:

These are very efficent packages: a 200-degree polynomial with real coefficients may be evaluated, using the horner member function, at half a million randomly-generated octonions per second.

The full package may be downloaded here.

Their dimensions are 2, 4, 8, 16, and 32, respectively. The justification for implementing yet-another-version of complex numbers is that most standard packages do not deal correctly with objects such as ∞ and NaN. For example, the absolute value of NaN + i∞ should be ∞ and not NaN. The remaining classes rely on the appropriate behaviour of the complex-number class to perform their calculations. The justification for implementing trigintaduonions is "for fun" — the sedenions already loose alternativity and is no longer a division algebra.

In addition to these systems, rotations, spherical interpolations, spherical Bezier curves, spherical splines, and fractals are either defined or also implemented as part of a class. While each of the curves could be easily implemented without the use of special classes, the classes define objects which allow faster computations of points on the curves.


The documentation summarizes the behaviour of the functions. The precise behaviour is not covered as the expected behaviour is well defined elsewhere, for example, wikipedia.


In most cases, aside from simple arithmetic, many of the trigonometric, hyperbolic, and inverse functions are implemented in the higher-order systems are calculated by mapping the problem to the complex domain, solving the problem there, and then mapping back to the appropriate domain.

These packages attempt, in many cases, to deal correctly with objects such as NaN, plus or minus infinity, and plus or minus zero. The latter is often most interesting, as it is very relevant with branch cuts.

Cayley-Dickson Construction

First, we define the reals R where aR implies that a* = a. Given an algebra A of diminsion n, we create, using the Cayley-Dickson construction, an algebra of dimension 2n by taking pairs (a, b) ∈ A × A and thus define the standard operations:

1 = (1, 0)
−(a, b) = (−a, −b)
(a, b)* = (a*, −b)
(a, b) + (c, d) = (a + c, b + d)
(a, b)(c, d) = (acd*b, da + bc*)

In order to maintain a standard behaviour, a variation of the Cayley-Dickson construction shown in wikipedia is used for calculating products in higher dimensions. The justification is that it would be nice if the original quaternion identity ijk = -1 holds — the variation on wikipedia defines ijk = 1.

Note that

(a, b)(a, b)* = (ab)(a*, −b) = (aa* + b*b, −ba + ba) = (aa* + bb*, 0)

Other properties include that each of these algebras are nicely normed in that |z|2 = zz*z*z and consequently, the inverse of any element is defined as z-1 = z*/|z|2, however, once there are zero divisors (sedenions-dimension 16-and above), the construction is no longer a conposition algebra, that is, it is not necessarily true that |wz| = |w||z|.

Note also that if z = (ab) then |z|2 = |a|2 + |b|2.

A real number a is imaginary if and only if a = 0. A constructed pair (ab) is imaginary if and only if a is imaginary. If z is imaignary, then z* = −z and consequently, for imaginary z, z2 = −zz* = −|z|2.

A full test of the Cayley-Dickson construction is found in cayley.cpp in the source directory.


A rather thorough tester is implemented in unit.cpp. The most detectable weakness is that the inverse hyperbolic sine function fails when |ℜ(z)| << |ℑ(z)|, though the effect is still reasonably insignificant. This suggests, however, that special code should be implemented for the case where |ℜ(z)| << |ℑ(z)|.