Fast, cross validated multiplication and table generation for Cayley–Dickson algebras multiplication up to one million digit two elements index tested for O(1)/O(n) and depend on RAM allocation up to 2^13 or more for table builder.
For more info please visit All benchamrks in BENCHMARKS.md and Jupyter Notebook used in examples/benchmark/benchmark.ipynb (note speed time may vary depend on your hardware).
This library provides the computational substrate for high-dimensional hypercomplex algebra, featuring:
- Full multiplication table generation for standard, split, and dual algebras.
- O(n) holographic table-free recursive descent multiplication.
- O(1) fast bitwise closed-form multiplication.
- Integer, graded, and LaTeX notation formatting.
- CSV export for tables (matrix and long formats).
- A simple facade API for everyday use, and direct low-level classes for advanced physics/math engines.
If you build upon this package, please read fully Go to Scope, Strengths, and Limitations below for more information or check Scope, Strengths, and Limitations file
This library serves as the formal verification substrate and computational engine for the following mathematical preprints:
1. The Sign Structure of Cayley–Dickson and Split Algebras By Blocks
Proves the OPMT (Ordered-Pair Multiplication Table) sign laws, block decomposition, and the O(1) closed-form sign evaluator implemented in the fast engine of this library.
- 📊 Figshare: 10.6084/m9.figshare.33705022
- 📦 Zenodo: 10.5281/zenodo.22051873
| Kind | Description |
|---|---|
standard |
Ordinary Cayley–Dickson algebras: real, complex, quaternions, octonions, sedenions, ... |
split |
Split Cayley–Dickson algebras: standard parent plus one split doubling at the top |
dual |
Dual extension of a standard algebra, with ε² = 0 |
dual_split |
Dual extension of a split algebra, with ε² = 0 |
Clone the repository:
git clone https://github.com/maher1719/hypercomplex-engine.git
cd hypercomplex-engineInstall with pip:
pip install hypercomplex-engineInstall in editable mode:
pip install -e .Run the tests:
pytest -vThe simplest way to use the library is through the top-level facade API.
from hypercomplex import (
build_table,
multiply,
format_element,
print_table,
export_csv,
)table = build_table("standard", 3)This builds the octonion multiplication table.
Dimensions:
n = 0 -> real numbers, dimension 1
n = 1 -> complex numbers, dimension 2
n = 2 -> quaternions, dimension 4
n = 3 -> octonions, dimension 8
n = 4 -> sedenions, dimension 16
print_table(table, title="Octonions", mode="integer")Example output style:
e0 e1 e2 e3 e4 e5 e6 e7
e0 | +e0 +e1 +e2 +e3 +e4 +e5 +e6 +e7
e1 | +e1 -e0 +e3 -e2 +e5 -e4 -e7 +e6
...
You can also use graded notation:
print_table(table, title="Octonions", mode="graded")Example:
1 o1 o2 o3 o4 o5 o6 o7
1 | +1 +o1 +o2 +o3 +o4 +o5 +o6 +o7
o1 | +o1 -1 ...
...
Matrix-style CSV:
export_csv(
"octonions_graded.csv",
table,
mode="graded",
csv_mode="matrix",
)Long-format CSV for data analysis:
export_csv(
"octonions_long.csv",
table,
mode="integer",
csv_mode="long",
)The long format produces rows like:
i,j,sign,index
0,0,1,0
0,1,1,1
1,0,1,1
1,1,-1,0
...result = multiply("standard", (1, 1), (1, 2))
print(result)
# (1, 3)This means:
e1 * e2 = +e3
Format the result:
print(format_element(result, mode="integer"))
# +e3
print(format_element(result, mode="graded"))
# +o12
print(format_element(result, mode="latex"))
# +e_{3}Note:
integer mode uses the basis index:
e3
graded mode uses the generator decomposition:
index 3 = binary 011 = generators 1 and 2 = o12
result = multiply("split", (1, 1), (1, 1), dim=1)
print(result)
# (1, 0)In split-complex numbers:
e1² = +e0
# eps*e0 represented as local tuple: (sign, local_index, eps_flag)
eps_e0 = (1, 0, 1)
result = multiply("dual", (1, 0), eps_e0, dim=1)
print(result)
# (1, 0, 1)
print(format_element(result, mode="integer"))
# +epsNilpotency:
result = multiply("dual", eps_e0, eps_e0, dim=1)
print(result)
# (0, 0, 0)This means:
ε² = 0
The facade API is enough for most users.
For more control, you can choose the computation engine and work directly with tables or multipliers.
The multiply function supports two engines:
multiply(kind, a, b, dim=None, engine="fast")| Engine | Complexity | Description |
|---|---|---|
"fast" |
O(1) | Bitwise closed-form sign evaluator |
"holographic" |
O(n) | Recursive block descent |
Example:
from hypercomplex import multiply
a = (1, 3)
b = (1, 5)
fast_result = multiply("standard", a, b, engine="fast")
holo_result = multiply("standard", a, b, engine="holographic")
assert fast_result == holo_resultmultiply("standard", a, b)
multiply("split", a, b, dim=3)
multiply("dual", a, b, dim=3)
multiply("dual_split", a, b, dim=3)For standard, dim is not needed.
For split, dual and dual_split, dim is required.
from hypercomplex import (
StandardTableBuilder,
SplitTableBuilder,
DualTableBuilder,
)
standard_builder = StandardTableBuilder()
split_builder = SplitTableBuilder()
dual_builder = DualTableBuilder()
signs, indices = standard_builder.build(3)
signs, indices = split_builder.build(3)
signs, indices, eps = dual_builder.build(2, split=False)Return conventions:
standard:
signs, indices
split:
signs, indices
dual:
signs, indices, eps
For dual tables:
signs[i, j]is the sign.indices[i, j]is the local base index.eps[i, j]is the epsilon flag.
from hypercomplex import (
StandardHolographic,
SplitHolographic,
DualHolographic,
)
holo = StandardHolographic()
result = holo.multiply((1, 1), (1, 2))
print(result)
# (1, 3)Split:
split_holo = SplitHolographic()
result = split_holo.multiply((1, 2), (1, 2), dim=2)
print(result)
# (1, 0)Dual:
dual_holo = DualHolographic(split=False)
result = dual_holo.multiply((1, 0), (1, 2), dim=1)
print(result)
# (1, 0, 1)from hypercomplex import (
FastStandard,
FastSplit,
FastDual,
)
fast = FastStandard()
result = fast.multiply((1, 1), (1, 2))
print(result)
# (1, 3)Split:
fast_split = FastSplit()
result = fast_split.multiply((1, 2), (1, 2), dim=2)
print(result)
# (1, 0)Dual:
fast_dual = FastDual(split=False)
result = fast_dual.multiply((1, 0), (1, 0, 1), dim=1)
print(result)
# (1, 0, 1)| Mode | Example |
|---|---|
"integer" |
+e5 |
"graded" |
+o13 |
"latex" |
+e_{5} |
"latex_integer" |
+e_{5} |
"latex_graded" |
+o_{13} |
Example:
from hypercomplex import format_element
element = (-1, 5)
print(format_element(element, mode="integer"))
# -e5
print(format_element(element, mode="graded"))
# -o13
print(format_element(element, mode="latex"))
# -e_{5}
print(format_element(element, mode="latex_integer"))
# -e_{5}
print(format_element(element, mode="latex_graded"))
# -o_{13}This section is for contributors, benchmarking, physics engines, and symbolic pipelines.
If you prefer explicit imports:
from hypercomplex.core.table_builder import (
StandardTableBuilder,
SplitTableBuilder,
DualTableBuilder,
)
from hypercomplex.core.holographic import (
StandardHolographic,
SplitHolographic,
DualHolographic,
)
from hypercomplex.core.fast import (
FastStandard,
FastSplit,
FastDual,
)
from hypercomplex.printer import (
CDFormat,
CDTablePrinter,
)from hypercomplex import StandardTableBuilder, FastStandard
builder = StandardTableBuilder()
fast = FastStandard()
n = 4
signs, indices = builder.build(n)
dim = 1 << n
for i in range(dim):
for j in range(dim):
fast_sign, fast_idx = fast.multiply_indices(i, j)
assert int(signs[i, j]) == fast_sign
assert int(indices[i, j]) == fast_idxThis proves that the O(1) evaluator agrees with the O(4^n) table builder.
from hypercomplex import SplitTableBuilder, FastSplit
builder = SplitTableBuilder()
fast = FastSplit()
n = 4
signs, indices = builder.build(n)
dim = 1 << n
for i in range(dim):
for j in range(dim):
fast_sign, fast_idx = fast.multiply_indices(i, j, dim=n)
assert int(signs[i, j]) == fast_sign
assert int(indices[i, j]) == fast_idxFor dual multiplication, the total dimension is:
2^(dim + 1)
The epsilon bit is bit dim.
Example for dim=1:
lower half: 0, 1 base elements
upper half: 2, 3 epsilon elements
The dual multipliers accept both:
# global index tuple
(1, 2)
# local tuple with epsilon flag
(1, 0, 1)Both represent ε·e₀ when dim=1.
The output convention is:
(sign, local_index, eps_flag)This makes formatting easy:
from hypercomplex import format_element
result = (1, 0, 1)
print(format_element(result, mode="integer"))
# +eps
print(format_element(result, mode="latex"))
# +\epsilonFor simulations, avoid building large tables. Use the fast engine directly.
from hypercomplex import FastStandard
fast = FastStandard()
def basis_product(i: int, j: int):
sign, index = fast.multiply((1, i), (1, j))
return sign, index
sign, index = basis_product(1, 2)
print(sign, index)
# 1 3For octonionic or higher-dimensional simulations, this avoids O(4^n) memory.
Full table generation grows as:
entries = 4^n
where n is the dimension exponent.
| n | Dimension | Entries |
|---|---|---|
| 0 | 1 | 1 |
| 1 | 2 | 4 |
| 2 | 4 | 16 |
| 3 | 8 | 64 |
| 4 | 16 | 256 |
| 5 | 32 | 1,024 |
| 6 | 64 | 4,096 |
| 8 | 256 | 65,536 |
| 10 | 1,024 | 1,048,576 |
| 12 | 4,096 | 16,777,216 |
For large dimensions, prefer:
engine="fast"or:
engine="holographic"Builds a multiplication table.
table = build_table("standard", 3)Returns:
standard:
(signs, indices)
split:
(signs, indices)
dual:
(signs, indices, eps)
dual_split:
(signs, indices, eps)
Multiplies two basis elements.
result = multiply("standard", (1, 1), (1, 2))Returns:
standard:
(sign, index)
split:
(sign, index)
dual:
(sign, local_index, eps_flag)
dual_split:
(sign, local_index, eps_flag)
Formats a basis element tuple.
format_element((1, 3), mode="integer")
# "+e3"
format_element((1, 3), mode="graded")
# "+o12"Prints a table.
table = build_table("standard", 2)
print_table(table, mode="graded")Exports a table to CSV.
table = build_table("standard", 3)
export_csv(
"octonions.csv",
table,
mode="graded",
csv_mode="matrix",
)CSV modes:
csv_mode |
Output |
|---|---|
"matrix" |
Spreadsheet-style grid |
"long" |
One row per product |
| Kind | Meaning |
|---|---|
"standard" |
Ordinary Cayley–Dickson |
"split" |
Split Cayley–Dickson |
"dual" |
Dual extension of standard algebra |
"dual_split" |
Dual extension of split algebra |
Aliases:
standard: "std", "ordinary", "o"
split: "s"
dual: "d", "dual_standard"
dual_split: "split_dual", "ds"
| Engine | Aliases | Complexity |
|---|---|---|
"fast" |
"o1", "bitwise", "constant" |
O(1) Word-RAM |
"holographic" |
"on", "descent" |
O(n) |
For standard and split Cayley–Dickson algebras:
e_i * e_j = sign(i, j) * e_{i XOR j}
The index is always:
i XOR j
The sign is determined by the OPMT block laws.
(a, b)(c, d) = (ac - d* b, da + b c*)
with conjugation:
e0* = e0
ek* = -ek for k > 0
(a, b)(c, d) = (ac + d* b, da + b c*)
The only difference from the standard construction is the sign of the d* b term.
This causes Block d signs to invert relative to the standard algebra.
Each multiplication table splits into four blocks:
[ a b ]
[ c d ]
where:
Block a: e_i * e_j
Block b: e_i * (e_j ℓ)
Block c: (e_i ℓ) * e_j
Block d: (e_i ℓ) * (e_j ℓ)
For standard algebras:
Block d interior sign = -σ_a
For split algebras:
Block d interior sign = +σ_a
Dual algebras adjoin ε such that:
ε² = 0
Multiplication rules:
e_i * e_j = parent product
e_i * (ε e_j) = ε (e_i e_j)
(ε e_i) * e_j = ε (e_i e_j)
(ε e_i) * (ε e_j) = 0
| Operation | Complexity | Memory |
|---|---|---|
| Full table generation | O(4^n) | O(4^n) |
| Holographic multiplication | O(n) | O(1) |
| Fast bitwise multiplication | O(1) Word-RAM | O(1) |
For arbitrary-precision integers, the fast evaluator uses O(n) bit operations, where:
n = ceil(log2(max(i, j) + 1))
Run all tests:
pytest -vRun specific test files:
pytest tests/test_mega_mother.py -v
pytest tests/test_fast_mode.py -vThe test suite validates:
- Basis notation conversion.
- Input validation.
- Standard table generation.
- Split table generation.
- Dual table generation.
- Holographic O(n) multiplication.
- Fast O(1) multiplication.
- Cross-validation between tables and multipliers.
- Facade API behavior.
- CSV export.
hypercomplex-engine/
├── examples/
│ ├── direct_implementation/
│ │ └── full_table_builder_simple.py
│ └── uses/
│ ├── outputs/
│ └── use.ipynb
├── hypercomplex/
│ ├── core/
│ │ ├── basis_element.py
│ │ ├── basis_notation.py
│ │ ├── validation.py
│ │ ├── table_builder/
│ │ │ ├── common.py
│ │ │ ├── standard.py
│ │ │ ├── split.py
│ │ │ └── dual.py
│ │ ├── holographic/
│ │ │ ├── standard.py
│ │ │ ├── split.py
│ │ │ └── dual.py
│ │ └── fast/
│ │ ├── bit_utils.py
│ │ ├── fast_standard.py
│ │ ├── fast_split.py
│ │ └── fast_dual.py
│ ├── printer/
│ │ ├── cd_format.py
│ │ └── cd_table_printer.py
│ ├── facade.py
│ └── __init__.py
├── tests/
│ ├── test_algebra.py
│ ├── test_fast_mode.py
│ ├── test_holographic_vs_table.py
│ └── test_mega_mother.py
├── LICENSE
├── README.md
└── pyproject.toml
Status: 0.4.x, pre-1.0. The API can still change. Read this section before building on the package.
It computes the product of two signed basis elements of a Cayley–Dickson algebra: ±e_i × ±e_j → ±e_k (or zero in dual algebras). It is a low-level component, a sign and index calculator, not a number type. There are no coefficients, no sums, and no vectors.
- One job, small surface. About 2,000 lines, one dependency (NumPy), and multipliers that keep no per-call state.
- Two interchangeable engines.
fastis a closed-form bitwise evaluator. It does constant work per call for word-sized indices, and cost grows only with bit length for arbitrary-precision indices.holographicis an O(n) recursive descent, useful as a cross-check.
- Works where tables cannot. Only the two indices are needed, so indices hundreds of bits long are fine. Full tables need 4^n entries.
- Cross-validated. The test suite checks the table builders, the
fastengine and theholographicengine against each other. - Strict about types.
bool,float,strandlistinputs are rejected. Results are plain Pythonints. - Tested on Python 3.10–3.14 and with NumPy 1.22 and newer.
| Kind | Element form | dim |
Index range |
|---|---|---|---|
standard |
(sign, index) |
not used | any integer ≥ 0 (no upper bound, since there is no dim to check against) |
split |
(sign, index) |
required | 0 ≤ index < 2**dim |
dual, dual_split |
(sign, global_index) or (sign, local_index, eps) |
required | global: 0 ≤ i < 2**(dim+1); local: 0 ≤ i < 2**dim |
- Elements must be tuples. Integers only, and NumPy integers are accepted.
signshould be-1or+1. Note:multiplycurrently also accepts0as a formal zero and returns zero. Do not rely on this; it may be removed.- Dual elements have two spellings of the same thing. At
dim=3,(1, 9)and(1, 1, 1)both mean+ε·e1(global index8 + 1). - Known looseness: at
dim=3,(1, 9, 1)and even(1, 9, 0)are also accepted and read as+ε·e1. The second one contradicts itself, so don't rely on it. - The dual result is always
(sign, local_index, eps), andε·εgives(0, 0, 0).
Elements are plain tuples, so they do not remember which algebra produced them.
- Feeding a result from one
diminto an algebra of a differentdimis not detected if the index happens to be in range. - Mixing
standardandsplitelements is not detected. The same tuple means different things:e2·e2is-1in the standard algebra,+1insplitwithdim=2, and-1insplitwithdim>=3. - For
standard, nothing tells you an index is "too big for the octonions".
- No chain multiplication and no expressions.
multiplyis strictly binary. You can pass a result into the next call yourself, but you choose the bracketing. Fromn=3(octonions) upward multiplication is not associative, so(ab)canda(bc)can differ in sign. - No coefficients, sums, vectors, arrays, or parsing of expressions like
e1+e2+e12. This is planned for a separate package built on top of this one. - No addition, conjugation, norm, inverse, or division.
splitmeans one split doubling on top of a standard parent. Other sign patterns are not offered.dualanddual_splitextend a standard or split parent with a centralε, whereε² = 0.
| n | Standard | Split |
|---|---|---|
| 1 | complex, commutative | split-complex, commutative, has zero divisors |
| 2 | quaternions, associative, not commutative | split-quaternions, associative, not commutative |
| 3 | octonions, alternative, not associative | split-octonions, alternative, not associative, has zero divisors |
| ≥ 4 | sedenions and beyond: zero divisors, no longer alternative | no longer alternative |
Products follow the standard doubling (a, b)(c, d) = (ac − d*b, da + bc*) (split algebras flip the sign of the d*b term at the top level). Other conventions give isomorphic algebras with different tables, so comparing against another source may show sign differences after relabeling. For example, here e1·e2 = e3 and e1·e6 = −e7.
FastStandard, FastSplit, FastDual, StandardHolographic, SplitHolographic and DualHolographic are exported, but they validate differently from each other and from multiply. For example, FastSplit accepts a zero element while the other three reject it. Their multiply_indices methods do only minimal checks. Prefer multiply. These classes are not a stable API and are expected to become internal.
Full tables have 4**n entries. build_table refuses requests above a default memory budget (max_bytes, 256 MiB):
standardandsplitare allowed up ton = 13.dualanddual_splitare allowed up ton = 12, since they are one doubling larger.
Use estimate_table_bytes(kind, n) to check a size, and pass a larger max_bytes (or None) if you really mean it. In dual tables, sign == 0 marks ε·ε.
- Pin your dependency, for example
hypercomplex-engine>=0.4.1,<0.5. - Planned for 0.5.0, subject to change: stricter inputs (no zero elements, one dual form), and low-level classes made internal. Breaking changes will be listed in the release notes.
- Do not treat the package as 1.0-stable until it has been used by futur a palnned package the vector-and-expression package.
If you use this engine in your research, physics simulations, or geometric deep learning models, please cite the underlying theoretical preprints:
@article{ben abdessalem2026,
author = "maher ben abdessalem",
title = "{A Proven Sign Law for Cayley-Dickson Algebras: Ordinary, Split, dual Constructions and their computational proofs and implementations}",
year = "2026",
month = "9",
url = "https://figshare.com/articles/preprint/A_Proven_Sign_Law_for_Cayley-Dickson_Algebras_Ordinary_and_Split_Constructions/33705022",
doi = "10.6084/m9.figshare.33705022.v5"
}
The author gratefully acknowledges Greg Wilmot for his work on the structure of Cayley-Dickson algebras and for acknowledging the author's contribution to his paper "Structure of the Cayley-Dickson algebras" (arXiv:2505.11747).
- Guangbin Ren and Xin Zhao, "The Explicit Twisted Group Algebra Structure of the Cayley–Dickson Algebra," Advances in Applied Clifford Algebras 33, Article 49 (2023). https://doi.org/10.1007/s00006-023-01296-6 · arXiv:2205.07986.
Apache 2.0 License.
See LICENSE for details.
Copyright (c) 2026 Maher Ben Abdessalem