480 varieties of octonion multiplication.
Version of Tuesday 8 December 2015.
Dave Barber's e-mail and other pages.

Thanks to Bob Smith for review.

This report presents a simple C++11 program that furnishes all 480 varieties of multiplication of octonions over the real numbers. Everyone is welcome to use, modify, and republish the source code.

There are eight unit octonions, notated:

 e0 e1 e2 e3 e4 e5 e6 e7

where e0 is identified with the real number unity, and the other units are termed imaginaries because they exhibit the property en2 = −e0.

A prefix tilde represents conjugation, so that ~a is the conjugate of a. Octonionic conjugation negates all the imaginary parts, but leaves e0 unchanged.

In the program output, an octonion is written as an ordered octet between square brackets, with e0 first and e7 last.

The heart of the program is the file raw_mult.h, which contains 480 multiplication tables, each with an identifying number between 0 and 479, all stored in a three-dimensional array named raw_mult. There is no particular connection between the values in a table and the table's identifying number. Here is an excerpt of raw_mult:

```int const raw_mult[480][8][8] {
//   0: [ 123 145 167 247 256 346 375 ]
{ { +8, +1, +2, +3, +4, +5, +6, +7 },
{ +1, -8, -3, +2, -5, +4, -7, +6 },
{ +2, +3, -8, -1, -7, -6, +5, +4 },
{ +3, -2, +1, -8, -6, +7, +4, -5 },
{ +4, +5, +7, +6, -8, -1, -3, -2 },
{ +5, -4, +6, -7, +1, -8, -2, +3 },
{ +6, +7, -5, -4, +3, +2, -8, -1 },
{ +7, -6, -4, +5, +2, -3, +1, -8 } },
//   1: [ 123 145 167 247 256 346 375 ]
{ { +8, +1, +2, +3, +4, +5, +6, +7 },
{ +1, -8, +3, -2, +5, -4, +7, -6 },
{ +2, -3, -8, +1, +7, +6, -5, -4 },
{ +3, +2, -1, -8, +6, -7, -4, +5 },
{ +4, -5, -7, -6, -8, +1, +3, +2 },
{ +5, +4, -6, +7, -1, -8, +2, -3 },
{ +6, -7, +5, +4, -3, -2, -8, +1 },
{ +7, +6, +4, -5, -2, +3, -1, -8 } },

// ... much omitted ...

// 245: [ 132 145 176 247 265 346 357 ]
{ { +8, +1, +2, +3, +4, +5, +6, +7 },
{ +1, -8, -3, +2, +5, -4, -7, +6 },
{ +2, +3, -8, -1, +7, -6, +5, -4 },
{ +3, -2, +1, -8, +6, +7, -4, -5 },
{ +4, -5, -7, -6, -8, +1, +3, +2 },
{ +5, +4, +6, -7, -1, -8, -2, +3 },
{ +6, +7, -5, +4, -3, +2, -8, -1 },
{ +7, -6, +4, +5, -2, -3, +1, -8 } },

// ... much omitted ...

// 479: [ 154 163 172 243 265 357 476 ]
{ { +8, +1, +2, +3, +4, +5, +6, +7 },
{ +1, -8, -7, -6, -5, +4, +3, +2 },
{ +2, +7, -8, -4, +3, -6, +5, -1 },
{ +3, +6, +4, -8, -2, +7, -1, -5 },
{ +4, +5, -3, +2, -8, -1, -7, +6 },
{ +5, -4, +6, -7, +1, -8, -2, +3 },
{ +6, -3, -5, +1, +7, +2, -8, -4 },
{ +7, -2, +1, +5, -6, -3, +4, -8 } }
};
```

The multiplication tables also appear in HTML format, divided into four sets because of size:

Here are side-by-side samples from HTML and raw_mult, which will help in the interpretation of raw_mult:

octonion multiplication 381
3812nd
e0e1e2e3e4e5e6e7
1ste0+e0+e1+e2+e3+e4+e5+e6+e7
e1+e1e0e6+e7e5+e4+e2e3
e2+e2+e6e0+e5+e7e3e1e4
e3+e3e7e5e0+e6+e2e4+e1
e4+e4+e5e7e6e0e1+e3+e2
e5+e5e4+e3e2+e1e0+e7e6
e6+e6e2+e1+e4e3e7e0+e5
e7+e7+e3+e4e1e2+e6e5e0
```// 381: [ 137 154 162 235 247 346 567 ]
{ { +8, +1, +2, +3, +4, +5, +6, +7 },
{ +1, -8, -6, +7, -5, +4, +2, -3 },
{ +2, +6, -8, +5, +7, -3, -1, -4 },
{ +3, -7, -5, -8, +6, +2, -4, +1 },
{ +4, +5, -7, -6, -8, -1, +3, +2 },
{ +5, -4, +3, -2, +1, -8, +7, -6 },
{ +6, -2, +1, +4, -3, -7, -8, +5 },
{ +7, +3, +4, -1, -2, +6, -5, -8 } }
```

In the HTML table, "1st" stands for the first factor, and "2nd" for the second.

Within raw_mult, the number +8 is an arbitrary symbol to represent +e0, while −8 stands for −e0. The other numbers are more direct, with +1 as +e1, −1 as −e1, +2 as +e2, et cetera. The program decodes the numbers to determine what the result of each unit multiplication will be. Essential to making this work is that octonion multiplication follows the distributive law.

Within the raw_mult comment, [ 137 154 162 235 247 346 567 ] is a list of seven quaternionic triples. For instance, 137 says that the product of any two members of the set { e1, e3, e7 } will be the other member, with either a positive or a negative sign. Specifically, with integers i, j, k in the range [1, 7]:

if then ei ej = +ek ei ej = −ek ej ek = +ei ek ei = +ej ei ek = −ej ek ej = −ei ej ei = −ek ej ek = −ei ek ei = −ej ei ek = +ej ek ej = +ei ej ei = +ek

For integer n, multiplication tables 2n and 2n + 1 will have the same list of quaternionic triplets, and will differ only in certain signs.

An example of table use: Under multiplication rule 381, e2 times e5 equals −e3. Meanwhile, e5 times e2 equals +e3, illustrating that octonion multiplication is not commutative.

The raw_mult array was generated by a separate C++ program not included in the download.

File octonion.h contains a class to do octonion arithmetic. For clarity of explication, many details that would be important in production code have been omitted from the class, but the user can restore them as desired. Among other things, the component numerical type (here double) would probably be made into a template parameter. Too, improvements can be made in efficiency and error checking.

The key function is:

• octonion mult (octonion const & second, int const choose_mult) const
which does the multiplying:
• The object on which the function is called serves as the first factor.
• Parameter second is the second factor.
• Parameter choose_mult, taking values from 0 to 479, determines which multiplication table will be used.

There is always a default multiplication table in effect; the initial value is an arbitrarily-selected 42. This function:

• octonion operator* (octonion const & second) const
uses the default implicitly, and this function:
• static void set_default_mult (int const choose_mult)
changes it.

The third file, demo.h, contains four demonstrator functions which carry out sample calculations on random-looking numbers.

♦ Function demo1 verifies various algebraic laws.

♦ Function demo2 calculates all 480 products of two octonions, and displays them in a sorted list to verify that all the products are different.

♦ Functions demo3 and demo4 illustrate invariance. For all ordered pairs of octonions (a, b), the expression (a b) a takes on the same value no matter which of the 480 multiplication tables is used, as long as the same table is used for both multiplications. The same can be said of (~a) (ab). Further,

a (b a) = (a b) a
(~a) (ab) = ((~a) a) b = b (a (~a)) = (ba) (~a)

Thus one can unambiguously write ab a or ~aab respectively. In octonion.h are two compound multiplication functions to calculate these directly, without regard to any of the 480 multiplication tables:

• ab aoctonion mult_aba (octonion const & second) const
• ~aaboctonion mult_conj_aab (octonion const & second) const
In both cases, the object on which the function is called is a, and second is b.

Note that invariance does not occur with all sequences of factors. For instance, (a a) b is not invariant even though (a a) b will equal a (a b) for any fixed choice of multiplication table. Similarly, (ab) (~a) and a (b (~a)) are not invariant.

Employing an ordered triple of arbitrary quaternions (a, b, c), the following five-element associations also exhibit invariance:

 ( a b ) ( ( c b ) a ) ( a ( b c ) ) ( b a ) ( ( ( a b ) c ) b ) a a ( b ( c ( b a ) ) ) ( a ( ( b c ) b ) ) a a ( ( b ( c b ) ) a ) a ( ( ( b c ) b ) a ) ( a ( b ( c b ) ) ) a

These are eight of the fourteen possible associations.

♦ Function demo5 addresses the distributivity of the compound multiplications. A more conventional mathematical infix notation is helpful to explain this:

• first.mult_aba (second)a ⊗′ b
• first.mult_conj_aab (second)a ⊗″ b

Distributivity is one-sided:

 True: a ⊗′ (b + c) = a ⊗′ b + a ⊗′ c a ⊗″ (b + c) = a ⊗″ b + a ⊗″ c False: (a + b) ⊗′ c = a ⊗′ c + b ⊗′ c (a + b) ⊗″ c = a ⊗″ c + b ⊗″ c

The fourth file, main.cpp, contains the main routine and a few overhead items.

A program that will use only one multiplication table throughout its entire run will likely invoke set_default_mult just once, when initializing, to be followed by many calls of operator* in a set-and-forget arrangement. On the other hand, function mult is convenient when a single calculation will use several different multiplication tables, as in the following mixed-multiplication calculations (introducing an obvious prefix notation) which, although unconventional by octonion standards, are well defined:

mul286 (mul354 (a, b), c)
mul128 (a, b) + mul99 (c, d)

A result that uses mixed multiplication is, for integer n:

mul2n (a, b) = mul2n+1 (b, a)

For integer n and m, invariance can be precisely notated thus:

muln (a, muln (b, a)) = mulm (a, mulm (b, a))

The multiplication tables on this site, although developed separately and by a different method, are consistent with those of Gregory Moxness.

While all 480 octonion multiplication tables are essentially the same, some are preferred by researchers because the e subscripts form a convenient pattern. As given by Geoffrey Dixon, these favorites are named C(+), C(−), D(+), and D(−), corresponding to tables 406, 407, 145, and 144 respectively.

C(+)
406
2nd
e0e1e2e3e4e5e6e7
1ste0+e0+e1+e2+e3+e4+e5+e6+e7
e1+e1e0+e4+e7e2+e6e5e3
e2+e2e4e0+e5+e1e3+e7e6
e3+e3e7e5e0+e6+e2e4+e1
e4+e4+e2e1e6e0+e7+e3e5
e5+e5e6+e3e2e7e0+e1+e4
e6+e6+e5e7+e4e3e1e0+e2
e7+e7+e3+e6e1+e5e4e2e0
C(−)
407
2nd
e0e1e2e3e4e5e6e7
1ste0+e0+e1+e2+e3+e4+e5+e6+e7
e1+e1e0e4e7+e2e6+e5+e3
e2+e2+e4e0e5e1+e3e7+e6
e3+e3+e7+e5e0e6e2+e4e1
e4+e4e2+e1+e6e0e7e3+e5
e5+e5+e6e3+e2+e7e0e1e4
e6+e6e5+e7e4+e3+e1e0e2
e7+e7e3e6+e1e5+e4+e2e0
D(+)
145
2nd
e0e1e2e3e4e5e6e7
1ste0+e0+e1+e2+e3+e4+e5+e6+e7
e1+e1e0+e6+e4e3+e7e2e5
e2+e2e6e0+e7+e5e4+e1e3
e3+e3e4e7e0+e1+e6e5+e2
e4+e4+e3e5e1e0+e2+e7e6
e5+e5e7+e4e6e2e0+e3+e1
e6+e6+e2e1+e5e7e3e0+e4
e7+e7+e5+e3e2+e6e1e4e0
D(−)
144
2nd
e0e1e2e3e4e5e6e7
1ste0+e0+e1+e2+e3+e4+e5+e6+e7
e1+e1e0e6e4+e3e7+e2+e5
e2+e2+e6e0e7e5+e4e1+e3
e3+e3+e4+e7e0e1e6+e5e2
e4+e4e3+e5+e1e0e2e7+e6
e5+e5+e7e4+e6+e2e0e3e1
e6+e6e2+e1e5+e7+e3e0e4
e7+e7e5e3+e2e6+e1+e4e0

Below are some excerpts from C(+) = 406 that make the pattern clear; the other three operations are similar:

e1e2e3e4e5e6e7
e1 +e4
e2  +e5
e3   +e6
e4    +e7
e5     +e1
e6      +e2
e7+e3
e1e2e3e4e5e6e7
e1   e2
e2    e3
e3     e4
e4      e5
e5e6
e6 e7
e7  e1
e1e2e3e4e5e6e7
e1  +e7
e2   +e1
e3    +e2
e4     +e3
e5      +e4
e6+e5
e7 +e6
e1e2e3e4e5e6e7
e1      e3
e2e4
e3 e5
e4  e6
e5   e7
e6    e1
e7     e2
e1e2e3e4e5e6e7
e1    +e6
e2     +e7
e3      +e1
e4+e2
e5 +e3
e6  +e4
e7   +e5
e1e2e3e4e5e6e7
e1     e5
e2      e6
e3e7
e4 e1
e5  e2
e6   e3
e7    e4

The tables in raw_mult can easily be adapted to the seven-dimensional cross product. The row and the column corresponding to factor e0 (now shown in a faint color) are ignored; and the diagonal elements that had been −e0 (represented by −8) are changed to zero, because the cross product of parallel vectors vanishes.

cross product 381
3812nd
e0e1e2e3e4e5e6e7
1ste0+e0+e1+e2+e3+e4+e5+e6+e7
e1+e10e6+e7e5+e4+e2e3
e2+e2+e60+e5+e7e3e1e4
e3+e3e7e50+e6+e2e4+e1
e4+e4+e5e7e60e1+e3+e2
e5+e5e4+e3e2+e10+e7e6
e6+e6e2+e1+e4e3e70+e5
e7+e7+e3+e4e1e2+e6e50
```// 381: [ 137 154 162 235 247 346 567 ]
{ { +8, +1, +2, +3, +4, +5, +6, +7 },
{ +1, -8, -6, +7, -5, +4, +2, -3 },
{ +2, +6, -8, +5, +7, -3, -1, -4 },
{ +3, -7, -5, -8, +6, +2, -4, +1 },
{ +4, +5, -7, -6, -8, -1, +3, +2 },
{ +5, -4, +3, -2, +1, -8, +7, -6 },
{ +6, -2, +1, +4, -3, -7, -8, +5 },
{ +7, +3, +4, -1, -2, +6, -5, -8 } }
```
different from the figure displayed earliersame as the figure displayed earlier

While octonions have 480 multiplication tables, quaternions have only two. The following equivalences effect the usual quaternionic notation:

 e0 = 1 e1 = i e2 = j e3 = k

With that, the tables look like this:

standard
quaternions
rare
variant
2nd
1ijk
1st1+1+i+j+k
i+i−1+kj
j+jk−1+i
k+k+ji−1
2nd
1ijk
1st1+1+i+j+k
i+i−1k+j
j+j+k−1i
k+kj+i−1

Historical note. John T. Graves and Arthur Cayley discovered the octonions separately, but at roughly the same time, in the mid-1840s. Table 5, below, is often cited as the first published octonion multiplication table, credited to Arthur Cayley in 1845.

52nd
e0e1e2e3e4e5e6e7
1ste0+e0+e1+e2+e3+e4+e5+e6+e7
e1+e1e0+e3e2+e5e4e7+e6
e2+e2e3e0+e1+e6+e7e4e5
e3+e3+e2e1e0+e7e6+e5e4
e4+e4e5e6e7e0+e1+e2+e3
e5+e5+e4e7+e6e1e0e3+e2
e6+e6+e7+e4e5e2+e3e0e1
e7+e7e6+e5+e4e3e2+e1e0

William Rowan Hamilton attributes to Graves (page 19, second footnote, in a collection edited by David Wilkins) a set of symbols generating the same table. Graves used letters i through o for the imaginary units when giving his multiplication rules, and table 5 emerges if the following equivalences are employed:

 i = e1 j = e2 k = e3 l = e4 m = e5 n = e6 o = e7

This is also the multiplication table that appeared on the Wikipedia octonion page in November of 2015.