The C++ classes `Octonion<long double>`, `Octonion<double>`, and `Octonion<float>`
represent floating-point octonions of the form *z* = *a* + *ib*_{1} + *jb*_{2} + *kb*_{3} + *ub*_{4} + *i*_{1}*b*_{5} + *j*_{1}*b*_{6} + *k*_{1}*b*_{7}.

Table 1. Multiplication rules for octonion symbols.

× | i | j | k | u_{1} | i_{1} | j_{1} | k_{1} |

i | −1 | k | −j | i_{1} | −u_{1} | −k_{1} | j_{1} |

j | −k | −1 | i | j_{1} | k_{1} | −u_{1} | −i_{1} |

k | j | −i | −1 | k_{1} | −j_{1} | i_{1} | −u_{1} |

u_{1} | −i_{1} | −j_{1} | −k_{1} | −1 | i | j | k |

i_{1} | u_{1} | −k_{1} | j_{1} | −i | −1 | −k | j |

j_{1} | k_{1} | u_{1} | −i_{1} | −j | k | −1 | −i |

k_{1} | −j_{1} | i_{1} | u_{1} | −k | −j | i | −1 |

This is also shown in Figure 1 where arrows indicate the order of multiplication resulting in a *positive* product. For
example, the lowest edge arrow would indicate that *j*_{1}*i* = *k*_{1}, and consequently, *ik*_{1} = *j*_{1}, and *k*_{1}*j*_{1} = *i*. These may
be confirmed by referring to Table 1.

Figure 1. Multiplication of symbols.

Consequently, multiplication is not associative:
(*ij*)*u*_{1} = *ku*_{1} = *k*_{1}, but
*i*(*ju*_{1}) = *ij*_{1} = −*k*_{1}.

Throughout this document, the variable *z* is used to represent `*this`
object. The choice of *u* over *e* for the additional symbol relates mostly
to the special nature of `e` in printing doubles. The template variable `T` represents the field of the coefficients.

- Constructors
- Constants
- Real-Valued Functions
- Octonion-Valued Functions
- Squares and Inverses
- Rotations
- Powers
- Exponential and Logarithmic Functions
- Trigonometric and Hyperbolic Functions (and their Inverses)
- Special Functions
- Integer-Value Functions
- Horner's Rule
- Binary Arithmetic Operators
- Unary Arithmetic Operators
- Assignment Operators
- Auto Increment and Auto Decrement Operators
- Binary Boolean Operators
- Query Functions
- Static Factory Functions
- Stream Operators

There are two constructors

Octonion( T a = 0 ); Octonion( T a, T b1, T b2, T b3, T b4, T b5, T b6, T b7 );

which create the octonions *a* + 0*i* + 0*j* + 0*k* + 0u_{1} + 0*i*_{1} + 0*j*_{1} + 0*k*_{1} and
*a* + *ib*_{1} + *jb*_{2} + *kb*_{3} + *ub*_{4} + *i*_{1}*b*_{5} + *j*_{1}*b*_{6} + *k*_{1}*b*_{7}, respectively.

There are nine static constants defined in each class:

There are five static constants defined in each class:

ZERO | 0 |

ONE | 1 |

I | i |

J | j |

K | k |

U1 | u_{1} |

I1 | i_{1} |

J1 | j_{1} |

K1 | k_{1} |

The constants may be accessed through the array `UNITS[8] = {ONE, I, J, K, U1, I1, J1, K1}`.

Each of the real-valued member functions has the prototype
`T f() const;`
and has a corresponding procedural function `T f( const Octonion<T> );`.

real |
imag_i |
imag_j |
imag_k |
imag_u1 |
imag_i1 |
imag_j1 |

imag_k1 |
csgn |
abs |
norm |
abs_imag |
norm_imag |
arg |

Descriptions of each of the functions follow:

`real`- Return the real component ℜ(
*z*) =*a*. `imag_i`- Return the imaginary component ℑ
_{i}(*z*) =*b*_{1}. `imag_j`- Return the imaginary component ℑ
_{j}(*z*) =*b*_{2}. `imag_k`- Return the imaginary component ℑ
_{k}(*z*) =*b*_{3}. `imag_u1`- Return the imaginary component ℑ
_{u1}(*z*) =*b*_{4}. `imag_i1`- Return the imaginary component ℑ
_{i1}(*z*) =*b*_{5}. `imag_j1`- Return the imaginary component ℑ
_{j1}(*z*) =*b*_{6}. `imag_k1`- Return the imaginary component ℑ
_{k1}(*z*) =*b*_{7}. `csgn`- Return 0 if
*z*= 0, 1 if*a*≥ +0, and -1 if*a*≤ -0. `abs`- Return |
*z*| = (*zz*^{*})^{½}unless either component is infinity, in which case, it always returns ∞. `norm`- Returns |
*z*|^{2}=*zz*^{*}unless any component is infinity, in which case, it always returns ∞. `abs_imag`- Returns the absolute value of the imaginary part of the octonion: |ℑ(
*z*)| = (-ℑ(*z*)^{2})^{½}. `norm_imag`- Returns |ℑ(
*z*)|^{2}= -ℑ(*z*)^{2}. `arg`- Return the argument of the octonion arg(
*z*) = atan2( |ℑ(*z*)|, ℜ(*z*) ).

The function `T operator [](int n) const` returns the coefficient of
the unit `UNITS[n]` for *n* = 0, 1, 2, ..., 7.

Each of these octonion-valued member functions has the prototype
`Octonion<T> f() const;`
and has a corresponding procedural function `Octonion<T> f( const Octonion<T> );`.

imag |
conj |
signum |

Descriptions of each of the functions follow:

`imag`- Return the octonion 0 +
*ib*_{1}+*jb*_{2}+ ⋅⋅⋅ +*k*_{1}*b*_{7}. `cong`- Return the octonion
*z*^{*}=*a*−*ib*_{1}−*jb*_{2}− ⋅⋅ −*k*_{1}*b*_{7}. `signum`- Return the octonion
*z*/|*z*| given*z*≠ 0. If*z*= 0, then*z*is returned.

Each of the square, square root, and inverse member functions has the prototype
`Octonion<T> f() const;`
and has a corresponding procedural function `Octonion<T> f( const Octonion<T> );`.

sqr |
sqrt |
inverse |

Descriptions of each of the functions follow:

`sqr`- Calculate
*z*^{2}. `sqrt`- Calculate the square root of
*z*(that is,*z*^{½}). `inverse`- Calculate the inverse of
*z*(that is,*z*^{-1}).

The member function
`Octonion<T> rotate( const Octonion<T> w ) const;` and its associated procedural function
`Octonion<T> rotate( const Octonion<T> z, const Octonion<T> w )`
calculates *wzw*^{*}. If *w* has unit length and
*z* is an imaginary quaternion, then this member function returns
vector *z* rotated 2 arg(*w*) radians
around the line defined by ℑ(*w*).

The power function is overloaded with two prototypes:

Octonion<T> pow( T ) |
Octonion<T> pow( Octonion<T> ) |

Each of the exponential and logarithmic member functions has the prototype `Octonion<T> f() const;`
and has a corresponding procedural function `Octonion<T> f( const Octonion<T> );`.

exp |
log |
log10 |

Descriptions of each of the functions follow:

`exp`- Calculate
*e*^{z}. `log`- Calculate the natural logarithm ln(
*z*). `log10`- Calculate the base-10 logarithm log
_{10}(*z*).

Because of the loss of associativity, unless *x* and *y* commute,
exp(*x* + *y*) ≠ exp(*x*)exp(*y*),
log(*x**y*) ≠ log(*x*) + log(*y*), and
log_{10}(*x**y*) ≠ log_{10}(*x*) + log_{10}(*y*). For example,

but

Each of the trigonometric, hyperbolic, inverse trigonometric, and inverse hyperbolic
member functions has the prototype `Octonion<T> f() const;`
and has a corresponding procedural function `Octonion<T> f( const Octonion<T> );`.

sin |
cos |
tan |
sec |
csc |
cot |

sinh |
cosh |
tanh |
sech |
csch |
coth |

asin |
acos |
atan |
asec |
acsc |
acot |

asinh |
acosh |
atanh |
asech |
acsch |
acoth |

For example, the `sin` function calculates the result
of *z* − *z*^{3}/3! + *z*^{5}/5! − *z*^{7}/7! + *z*^{9}/9! − *z*^{11}/11! + ⋅⋅⋅ by using the formula

As with the exponential and logarithmic functions, because of the loss of associativity, the commonly understood trigonmetric identities no longer hold, for example,

cos(

but

cos(

however, double angle formulas continue to hold:
sin(2*x*) = 2sin(*x*)cos(*x*) and
cos(2*x*) = 2cos^{2}(*x*) − 1.

Bessel functions of the first kind, J_{n}(*z*) are implemented for integer values of *n*.
The prototype of the member function is `Octonion<T> bessel_J( int ) const;`
and there is the corresponding procedural function
`Octonion<T> bessel_J( int, const Octonion<T>) const;`.

Because the coefficients of the Taylor series for Bessel functions of the first kind are real, this function is well defined even for the non-commutative octonions.

Each of the integer-valued member functions has the prototype `Octonion<T> f() const;`
and has a corresponding procedural function `Octonion<T> f( const Octonion<T> );`.

floor |
ceil |

In both cases, the floor and ceiling, respectively, are calculated for each component.

The polynomial
*v*_{0}*z*^{n − 1} +
*v*_{1}*z*^{n − 2} +
*v*_{2}*z*^{n − 3} + ⋅⋅⋅
*v*_{n − 3}*z*^{2} +
*v*_{n − 2}*z* +
*v*_{n − 1} may be
calculated efficiently using Horner's rule. The array `v` of *n* entries
may be of type `T *`. The lack of commutativity dictates that the polynomial is not
well defined from octonionic coefficients, hence the coefficients are restricted
to real values.

Octonion<T> horner( T * v, unsigned int n );

The Newton polynomial with offsets:
*v*_{0}(*z* − c_{n − 1})(*z* − c_{n − 2})⋅⋅⋅(*z* − c_{3})(*z* − c_{2})(*z* − c_{1}) +

*v*_{1}(*z* − c_{n − 1})(*z* − c_{n − 2})⋅⋅⋅(*z* − c_{3})(*z* − c_{2}) +

*v*_{2}(*z* − c_{n − 1})(*z* − c_{n − 2})⋅⋅⋅(*z* − c_{3}) + ⋅⋅⋅ +

*v*_{n − 3}(*z* − c_{n − 1})(*z* − c_{n − 2}) +

*v*_{n − 2}(*z* − c_{n − 1}) +

*v*_{n − 1} may also be
calculated efficiently using Horner's rule. The arrays `v` and `c` of *n* entries
must be of type `T *`.

Octonion<T> horner( T * v, T * c, unsigned int n );

Similarly, due to commutativity, the coefficients and the offsets must be restricted to real values.

Corresponding to each of this functions is a procedural function which takes the variable
`z` as a first argument.

All binary arithmetic operators `operator ⋅` have the following prototypes:

+ |
- |
* |
/ |

Note that *z*/*w* is defined as *zw*^{-1}.

The unary arithmetic operator `operator -` has the prototype
`operator - ( const Octonion<T> & )` and returns
the negative of the octonion.

The assignment operators `operator ⋅` have the prototypes
`operator ⋅ ( const Octonion<T> & )` and
`operator ⋅ ( T )` and appropriately modifies and returns this
octonion. The operations are:

= |
+= |
-= |
*= |
/= |

The auto increment and auto decrement operators work on the real part of the octonion.

All binary Boolean operators have the following prototypes:

== |
!= |

Descriptions of each of the functions follow:

`operator ==`- Returns
`true`if all components return true under`==`. `operator !=`- Returns
`true`if any components return true under`!=`.

Each of the following member functions has the prototype `bool f() const;` and
returns a value based on the components of this octonion.

is_imaginary |
is_inf |
is_nan |
is_neg_inf |

is_pos_inf |
is_real |
is_real_inf |
is_zero |

Descriptions of each of the functions follow:

`is_imaginary`- Returns
`true`if this octonion has a zero real component (of the form 0 +*ib*_{1}+*jb*_{2}+ ⋅⋅⋅ +*k*_{1}*b*_{7}) and`false`otherwise. `is_inf`- Returns
`true`if any component of this is one of either +∞ or -∞ and`false`otherwise. `is_nan`- Returns
`true`if any component of this is`NaN`and`false`otherwise. `is_neg_inf`- Returns
`true`if this octonion is -∞ + 0*i*+ 0*j*+ ⋅⋅⋅ + 0*k*_{1}and`false`otherwise. `is_pos_inf`- Returns
`true`if this octonion is ∞ + 0*i*+ 0*j*+ ⋅⋅⋅ + 0*k*_{1}and`false`otherwise. `is_real`- Returns
`true`if this octonion has a zero imaginary component (of the form*a*+ 0*i*+ 0*j*+ ⋅⋅⋅ + 0*k*_{1}) and`false`otherwise. `is_real_inf`- Returns
`true`if this octonion is either +∞ + 0*i*+ 0*j*+ ⋅⋅⋅ + 0*k*_{1}or -∞ + 0*i*+ 0*j*+ ⋅⋅⋅ + 0*k*_{1}and`false`otherwise. `is_zero`- Returns
`true`if this octonion is 0 + 0*i*+ 0*j*+ ⋅⋅⋅ + 0*k*_{1}and`false`otherwise.

Each of the following static factory functions has the prototype `static Octonion<T> f() const;`
and returns a random octonion according to the following definitions:

`random`*r*_{1}+ i*r*_{2}+ j*r*_{3}+ k*r*_{4}+*u*_{1}*r*_{5}+ i_{1}*r*_{6}+ j_{1}*r*_{7}+ k_{1}*r*_{8}`random_real`*r*_{1}+ 0*i*+ 0*j*+ ⋅⋅⋅ + 0*k*_{1}.`random_imag`- 0 + i
*r*_{2}+ j*r*_{3}+ k*r*_{4}+*u*_{1}*r*_{5}+ i_{1}*r*_{6}+ j_{1}*r*_{7}+ k_{1}*r*_{8}

where *r*_{k} is a random real value.

The stream operators have been overloaded to print and read octonions.