clif-ga 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
clif_ga-0.1.0/LICENSE ADDED
@@ -0,0 +1,9 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 D. A. Jones
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
6
+
7
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
8
+
9
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
clif_ga-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,93 @@
1
+ Metadata-Version: 2.4
2
+ Name: clif-ga
3
+ Version: 0.1.0
4
+ Summary: Clifford-algebra engine: multivector inverse algorithms
5
+ Author: D. A. Jones
6
+ License: MIT License
7
+
8
+ Copyright (c) 2026 D. A. Jones
9
+
10
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
15
+
16
+ Project-URL: Homepage, https://github.com/dajonesy/engine
17
+ Project-URL: Documentation, https://clif-ga.readthedocs.io
18
+ Requires-Python: >=3.10
19
+ Description-Content-Type: text/markdown
20
+ License-File: LICENSE
21
+ Requires-Dist: numpy>=1.24
22
+ Requires-Dist: numba>=0.58
23
+ Provides-Extra: dev
24
+ Requires-Dist: jupyter; extra == "dev"
25
+ Requires-Dist: ipykernel; extra == "dev"
26
+ Requires-Dist: ruff; extra == "dev"
27
+ Requires-Dist: myst-nb; extra == "dev"
28
+ Requires-Dist: jupyter-cache; extra == "dev"
29
+ Requires-Dist: matplotlib; extra == "dev"
30
+ Requires-Dist: pytest; extra == "dev"
31
+ Requires-Dist: sphinx; extra == "dev"
32
+ Requires-Dist: furo; extra == "dev"
33
+ Dynamic: license-file
34
+
35
+ # clif
36
+
37
+ A research toolkit for numerical computations in Clifford / geometric algebras,
38
+ with an emphasis on **fast multivector inverses**, including a 6D inverse and
39
+ an emerging dimension-independent approach.
40
+
41
+ > **Status:** research prototype, not yet a packaged release.
42
+ > The API is unstable and the test suite is still being built out.
43
+ > Star the repo if you want to follow along.
44
+
45
+ ---
46
+
47
+ ## What's here
48
+
49
+ The package implements Clifford algebra with explicit ordinal indexing of
50
+ multivector components, efficient sign-table-based multiplication, and support
51
+ for arbitrary metric signature and degeneracy.
52
+ It's organized as four cooperating layers:
53
+
54
+ - `clif.context` — global algebra state (dimension, signature, degeneracy, grade table).
55
+ - `clif.sign_table` — builds/caches the multiplication sign table and a Numba-jitted fast
56
+ multiplier for dimensions < 8.
57
+ - `clif.multivector` — the `Accum` class, a multivector as a NumPy array of real coefficients indexed by ordinal.
58
+ - `clif.util` — construction, printing, grade projection, involutions, and inverse models for specific dimensions.
59
+ - `clif.tools` — primitive signtable support functions
60
+
61
+ Inverse algorithms live in `clif.inverse`:
62
+
63
+ - `clif.inverse.fls` (and `clif.inverse.sparse_fls`) — Faddeev–LeVerrier–Souriau based inverses, with even/odd-graded variants.
64
+ - `clif.inverse.euclidean` — inverse for Euclidean (positive-definite) signatures.
65
+ - `clif.inverse.newton` — iterative refinement via Newton–Schulz.
66
+
67
+ ## A worked example
68
+
69
+ ```python
70
+ from clif.context import Cl, Layout
71
+ from clif.multivector import Accum
72
+
73
+ Cl(1, 1, 1) # algebra with 1 positive, 1 negative, 1 null basis vector
74
+ A = Accum.random()
75
+ print(A)
76
+
77
+ Cl(1, 3) # spacetime algebra Cl(1,3)
78
+ Layout([1, -1, -1, -1]) # equivalent, explicit
79
+ ```
80
+
81
+ ## Documentation
82
+
83
+ Built locally with Sphinx:
84
+
85
+ ```bash
86
+ cd docs && make html
87
+ ```
88
+
89
+ Then open `docs/_build/html/index.html` in a browser.
90
+
91
+ ## License
92
+
93
+ MIT. See [LICENSE](LICENSE).
@@ -0,0 +1,59 @@
1
+ # clif
2
+
3
+ A research toolkit for numerical computations in Clifford / geometric algebras,
4
+ with an emphasis on **fast multivector inverses**, including a 6D inverse and
5
+ an emerging dimension-independent approach.
6
+
7
+ > **Status:** research prototype, not yet a packaged release.
8
+ > The API is unstable and the test suite is still being built out.
9
+ > Star the repo if you want to follow along.
10
+
11
+ ---
12
+
13
+ ## What's here
14
+
15
+ The package implements Clifford algebra with explicit ordinal indexing of
16
+ multivector components, efficient sign-table-based multiplication, and support
17
+ for arbitrary metric signature and degeneracy.
18
+ It's organized as four cooperating layers:
19
+
20
+ - `clif.context` — global algebra state (dimension, signature, degeneracy, grade table).
21
+ - `clif.sign_table` — builds/caches the multiplication sign table and a Numba-jitted fast
22
+ multiplier for dimensions < 8.
23
+ - `clif.multivector` — the `Accum` class, a multivector as a NumPy array of real coefficients indexed by ordinal.
24
+ - `clif.util` — construction, printing, grade projection, involutions, and inverse models for specific dimensions.
25
+ - `clif.tools` — primitive signtable support functions
26
+
27
+ Inverse algorithms live in `clif.inverse`:
28
+
29
+ - `clif.inverse.fls` (and `clif.inverse.sparse_fls`) — Faddeev–LeVerrier–Souriau based inverses, with even/odd-graded variants.
30
+ - `clif.inverse.euclidean` — inverse for Euclidean (positive-definite) signatures.
31
+ - `clif.inverse.newton` — iterative refinement via Newton–Schulz.
32
+
33
+ ## A worked example
34
+
35
+ ```python
36
+ from clif.context import Cl, Layout
37
+ from clif.multivector import Accum
38
+
39
+ Cl(1, 1, 1) # algebra with 1 positive, 1 negative, 1 null basis vector
40
+ A = Accum.random()
41
+ print(A)
42
+
43
+ Cl(1, 3) # spacetime algebra Cl(1,3)
44
+ Layout([1, -1, -1, -1]) # equivalent, explicit
45
+ ```
46
+
47
+ ## Documentation
48
+
49
+ Built locally with Sphinx:
50
+
51
+ ```bash
52
+ cd docs && make html
53
+ ```
54
+
55
+ Then open `docs/_build/html/index.html` in a browser.
56
+
57
+ ## License
58
+
59
+ MIT. See [LICENSE](LICENSE).
@@ -0,0 +1,92 @@
1
+ # file: clif/__init__.py
2
+ """
3
+ clif — a Python package for Clifford algebra.
4
+
5
+ This package implements Clifford algebra (geometric algebra) with a focus on
6
+ explicit ordinal indexing of multivector components, efficient sign-table-based
7
+ multiplication, and support for arbitrary metric signature and degeneracy.
8
+
9
+ Architecture
10
+ ------------
11
+ The package is organized as four cooperating layers:
12
+
13
+ 1. **context** — global algebra state (dimension, signature, degeneracy, grade table).
14
+ Call :func:`context.Initialize`, :func:`context.Layout`, or :func:`context.Cl`
15
+ to configure the algebra before constructing any multivectors.
16
+
17
+ 2. **sign_table** — builds and caches the multiplication sign table for the current
18
+ algebra, and generates a Numba-jitted fast multiplier for dimensions < 8.
19
+
20
+ 3. **multivector** — the :class:`multivector.Accum` class, which implements a
21
+ multivector as a NumPy array of real coefficients indexed by their ordinal
22
+ (a bitmask whose set bits name the basis vectors in the blade).
23
+
24
+ 4. **util** — convenience functions for constructing, printing, and operating on
25
+ multivectors (grade projection, involutions, random multivectors, inverses
26
+ for specific dimensions).
27
+
28
+ 5. **tools** — stand alone assistant functions
29
+
30
+ Inverse algorithms live in the :mod:`clif.inverse` sub-package:
31
+ :func:`clif.inverse.fls_inverse` (Faddeev–LeVerrier–Souriau based, with
32
+ :func:`even_inverse`/:func:`odd_inverse` variants and sparse counterparts),
33
+ :func:`clif.inverse.euclidean_inverse`, and
34
+ :func:`clif.inverse.newton_schulz` (iterative refinement).
35
+
36
+ Ordinal indexing convention
37
+ ---------------------------
38
+ An element of the algebra is identified by a non-negative integer whose binary
39
+ representation names the basis vectors it contains. In a 3-dimensional algebra::
40
+
41
+ 0 = 0b000 scalar (grade 0)
42
+ 1 = 0b001 e1 (grade 1)
43
+ 2 = 0b010 e2 (grade 1)
44
+ 3 = 0b011 e1^e2 (grade 2)
45
+ 4 = 0b100 e3 (grade 1)
46
+ 5 = 0b101 e1^e3 (grade 2)
47
+ 6 = 0b110 e2^e3 (grade 2)
48
+ 7 = 0b111 e1^e2^e3 = I (grade 3, pseudoscalar)
49
+
50
+ This ordering differs from the graded lexicographic ordering used in the public
51
+ ``clifford`` package (pygae) and is a deliberate design choice of this implementation.
52
+
53
+ Quick start
54
+ -----------
55
+ ::
56
+
57
+ from clif.context import Cl, Layout
58
+ from clif.multivector import Accum
59
+
60
+ Cl(1, 1, 1) # algebra with 1 positive, 1 negative, 1 null basis vector
61
+ A = Accum.random()
62
+ print(A)
63
+
64
+ Cl(1, 3) # spacetime algebra Cl(1,3)
65
+ Layout([1, -1, -1, -1]) # equivalent, explicit
66
+
67
+ Authors
68
+ -------
69
+ D. A. Jones (original implementation)
70
+ """
71
+
72
+ # ---- nice for the developer ---- (maybe)
73
+ from clif import context
74
+ from clif import sign_table
75
+ from clif import multivector
76
+ from clif import util
77
+ from clif import tools
78
+
79
+ # ---- all a user should need ----
80
+ from clif.context import Cl, Grade
81
+ from clif.multivector import Accum
82
+
83
+ __all__ = [
84
+ "context",
85
+ "sign_table",
86
+ "multivector",
87
+ "util",
88
+ "tools",
89
+ "Cl",
90
+ "Grade",
91
+ "Accum"
92
+ ]
@@ -0,0 +1,312 @@
1
+ # file: clif/context.py
2
+ """
3
+ Algebra context — global state for the current Clifford algebra.
4
+
5
+ This module holds the parameters that define the algebra in use: the number of
6
+ dimensions, the metric signature (which basis vectors square to −1), and the
7
+ degeneracy mask (which basis vectors square to 0). It also maintains the
8
+ pre-computed :data:`Grade` table and the active :class:`~clif.sign_table.SignTable`.
9
+
10
+ All multivectors created after a call to :func:`Initialize` (or the convenience
11
+ wrappers :func:`Layout` and :func:`Cl`) share the same algebra context.
12
+
13
+ .. warning::
14
+
15
+ The context is **module-level mutable state**. Two multivectors created
16
+ under different :func:`Initialize` calls are mathematically incompatible.
17
+ Each :class:`~clif.multivector.Accum` instance records the context at
18
+ the time of its creation; use :func:`Check` to verify compatibility before
19
+ operating on a pair.
20
+
21
+ Initialisation functions
22
+ ------------------------
23
+ Three entry points are provided for different workflows:
24
+
25
+ * :func:`Initialize` — specify dimension, signature mask, and degeneracy mask
26
+ directly (low-level, most explicit).
27
+ * :func:`Layout` — specify the metric signature as a list of ``{+1, 0, −1}``
28
+ values, one per basis vector.
29
+ * :func:`Cl` — specify the algebra as ``Cl(p, q, r)`` — ``p`` positive,
30
+ ``q`` negative, ``r`` degenerate basis vectors.
31
+
32
+ Examples
33
+ --------
34
+ Euclidean 3-space::
35
+
36
+ import clif.context as Clif
37
+ Clif.Cl(3) # Cl(3, 0, 0)
38
+
39
+ Minkowski spacetime (one time-like dimension)::
40
+
41
+ Clif.Cl(1, 3) # Cl(1, 3, 0)
42
+
43
+ Projective geometry (one degenerate dimension)::
44
+
45
+ Clif.Cl(3, 0, 1) # Cl(3, 0, 1)
46
+
47
+ Explicit per-axis metric::
48
+
49
+ Clif.Layout([1, 1, -1, 0])
50
+ """
51
+
52
+ import numpy as np
53
+ import clif.sign_table as ST
54
+ # NOTE: clif.inverse is imported lazily inside Initialize(). A top-level
55
+ # import here would be circular: context -> inverse/__init__ -> fls -> context.
56
+
57
+ # ---------------------------------------------------------------------------
58
+ # Module-level state
59
+ # ---------------------------------------------------------------------------
60
+
61
+ #: Number of basis vectors in the current algebra.
62
+ dimensions: int = 0
63
+
64
+ #: Bitmask selecting the basis vectors that square to −1.
65
+ #: Bit *k* is set when basis vector *e*\ (k+1) has negative signature.
66
+ signature: int = 0
67
+
68
+ #: Bitmask selecting the basis vectors that square to 0 (degenerate/null).
69
+ #: Bit *k* is set when basis vector *e*\ (k+1) is degenerate.
70
+ degenerate: int = 0
71
+
72
+ #: Grade table: ``Grade[i]`` is the number of set bits in ``i``, i.e. the
73
+ #: grade of the blade whose ordinal index is ``i``.
74
+ #: Recomputed by :func:`Initialize`.
75
+ Grade: np.ndarray = []
76
+
77
+ #: The active :class:`~clif.sign_table.SignTable` for the current algebra.
78
+ #: Set by :func:`Initialize`; ``None`` until the first call.
79
+ _ActiveTable = None
80
+
81
+ _ActiveInverse = None
82
+
83
+ # ---------------------------------------------------------------------------
84
+ # Derived quantities
85
+ # ---------------------------------------------------------------------------
86
+
87
+ def bases() -> int:
88
+ """Return the number of basis blades in the current algebra.
89
+
90
+ Equal to ``2 ** dimensions``.
91
+
92
+ Returns
93
+ -------
94
+ int
95
+ The number of basis blades.
96
+
97
+ Examples
98
+ --------
99
+ ::
100
+
101
+ Clif.Cl(3)
102
+ assert Clif.bases() == 8 # scalar + 3 vectors + 3 bivectors + 1 trivector
103
+ """
104
+ return 1 << dimensions
105
+
106
+
107
+ def mask() -> int:
108
+ """Return a bitmask covering all valid ordinal indices.
109
+
110
+ Equal to ``bases() - 1``.
111
+
112
+ Returns
113
+ -------
114
+ int
115
+ Bitmask with the lowest ``dimensions`` bits set.
116
+ """
117
+ return (1 << dimensions) - 1
118
+
119
+
120
+ # ---------------------------------------------------------------------------
121
+ # Internal helpers
122
+ # ---------------------------------------------------------------------------
123
+
124
+ def _build_grade_table( dimensions: int ) -> np.ndarray:
125
+ """Recompute the :data:`Grade` table for the current :data:`dimensions`.
126
+
127
+ ``Grade[i]`` equals the number of 1-bits (population count) in ``i``,
128
+ which is the grade of the blade with ordinal index ``i``.
129
+
130
+ This function modifies the module global :data:`Grade` in place.
131
+ """
132
+
133
+ table = np.empty( 1<<dimensions, dtype=np.uint8 )
134
+ table[0] = 0
135
+ for d in range( dimensions ):
136
+ m = 1<<d
137
+ for n in range( m ):
138
+ table[m + n] = 1 + table[n]
139
+ return table
140
+
141
+
142
+ # ---------------------------------------------------------------------------
143
+ # Initialisation entry points
144
+ # ---------------------------------------------------------------------------
145
+
146
+ def Initialize(d: int, s: int = 0, x: int = 0) -> None:
147
+ """Configure the algebra by specifying dimension and metric masks.
148
+
149
+ This is the lowest-level initialisation entry point. :func:`Layout` and
150
+ :func:`Cl` are more convenient for most uses.
151
+
152
+ Parameters
153
+ ----------
154
+ d : int
155
+ Number of basis vectors (dimensions of the vector space).
156
+ s : int, optional
157
+ Signature mask. Bit *k* is set when basis vector *e*\\ (k+1) squares
158
+ to −1. Default ``0`` gives a fully Euclidean algebra.
159
+ x : int, optional
160
+ Degeneracy mask. Bit *k* is set when basis vector *e*\\ (k+1) squares
161
+ to 0. Default ``0`` gives a non-degenerate algebra.
162
+
163
+ Notes
164
+ -----
165
+ Calling this function rebuilds the grade table and instantiates a new
166
+ :class:`~clif.sign_table.SignTable`. For dimensions ≥ 8 the sign
167
+ table is not pre-built (the Numba multiplier is not generated); a
168
+ different multiplication strategy is required for those cases.
169
+
170
+ Examples
171
+ --------
172
+ Euclidean 6-space::
173
+
174
+ Initialize(6)
175
+
176
+ Minkowski space (negative first axis)::
177
+
178
+ Initialize(4, s=0b0001)
179
+
180
+ Degenerate axis (projective)::
181
+
182
+ Initialize(4, x=0b1000)
183
+ """
184
+ global dimensions, signature, degenerate, Grade, _ActiveTable, _ActiveInverse
185
+ dimensions = d
186
+ signature = s
187
+ degenerate = x
188
+ Grade = _build_grade_table( d )
189
+ _ActiveTable = ST.SignTable(d, s, x)
190
+
191
+ from clif.inverse import tau_api # local: breaks the cycle
192
+ try:
193
+ _ActiveInverse = tau_api.get_inverter(get_signature()).inverse
194
+ except AssertionError:
195
+ # sparse_fls is the single source of truth on what it supports
196
+ # (currently d = 4..11, non-degenerate). Anything else: no inverse.
197
+ _ActiveInverse = None
198
+ return
199
+
200
+ def Layout(Signature: list) -> None:
201
+ """Configure the algebra from a per-axis metric list.
202
+
203
+ Parameters
204
+ ----------
205
+ Signature : list of int
206
+ A list of ``+1``, ``0``, or ``-1`` values, one per basis vector.
207
+ The first entry describes *e1*, the second *e2*, and so on.
208
+
209
+ Examples
210
+ --------
211
+ Euclidean 3D::
212
+
213
+ Layout([1, 1, 1])
214
+
215
+ Minkowski (time-first)::
216
+
217
+ Layout([1, -1, -1, -1])
218
+
219
+ Projective 3D (degenerate first axis)::
220
+
221
+ Layout([0, 1, 1, 1])
222
+ """
223
+ d = len(Signature)
224
+ s = 0
225
+ x = 0
226
+ for w in Signature[::-1]:
227
+ s <<= 1
228
+ x <<= 1
229
+ if w < 0:
230
+ s |= 1
231
+ elif w == 0:
232
+ x |= 1
233
+ Initialize(d, s, x)
234
+ return
235
+
236
+ def get_signature():
237
+ global dimensions
238
+ global signature
239
+ global degenerate
240
+ layout = []
241
+ for d in range(dimensions):
242
+ mask = 1 << d
243
+ if 0 != degenerate & mask:
244
+ this1 = 0
245
+ elif 0 != signature & mask:
246
+ this1 = -1
247
+ else:
248
+ this1 = 1
249
+ layout += [ this1 ]
250
+ return layout
251
+
252
+ def Cl(p: int, q: int = 0, r: int = 0) -> None:
253
+ """Configure the algebra as Cl(p, q, r).
254
+
255
+ Constructs the Clifford algebra with ``p`` basis vectors squaring to +1,
256
+ ``q`` squaring to −1, and ``r`` squaring to 0, in that order.
257
+
258
+ Parameters
259
+ ----------
260
+ p : int
261
+ Number of positive-signature (Euclidean) basis vectors.
262
+ q : int, optional
263
+ Number of negative-signature basis vectors. Default 0.
264
+ r : int, optional
265
+ Number of degenerate (null) basis vectors. Default 0.
266
+
267
+ Examples
268
+ --------
269
+ Euclidean 3-space ``Cl(3, 0)``::
270
+
271
+ Cl(3)
272
+
273
+ Spacetime algebra ``Cl(1, 3)``::
274
+
275
+ Cl(1, 3)
276
+
277
+ Conformal model of 3D space ``Cl(4, 1)``::
278
+
279
+ Cl(4, 1)
280
+ """
281
+ Layout( [1]*p + [-1]*q + [0]*r )
282
+ return
283
+
284
+
285
+ # ---------------------------------------------------------------------------
286
+ # Compatibility check
287
+ # ---------------------------------------------------------------------------
288
+
289
+ def Check(A, B) -> None:
290
+ """Assert that two multivectors share the same algebra context.
291
+
292
+ Parameters
293
+ ----------
294
+ A, B : :class:`~clif.multivector.Accum`
295
+ The two multivectors to compare.
296
+
297
+ Raises
298
+ ------
299
+ AssertionError
300
+ If the multivectors differ in dimension, signature, or degeneracy.
301
+
302
+ Notes
303
+ -----
304
+ This check is *not* called automatically during arithmetic for performance
305
+ reasons. Call it explicitly during debugging or testing.
306
+ """
307
+ assert A.dimensions == B.dimensions, \
308
+ f"Dimension mismatch: {A.dimensions} vs {B.dimensions}"
309
+ assert A.signature == B.signature, \
310
+ f"Signature mismatch: {A.signature:#010b} vs {B.signature:#010b}"
311
+ assert A.degenerate == B.degenerate, \
312
+ f"Degeneracy mismatch: {A.degenerate:#010b} vs {B.degenerate:#010b}"
@@ -0,0 +1,26 @@
1
+ # file: clif/inverse/__init__.py
2
+ # 2026.05.14 DAJones: created
3
+ # 2026.08.17 DAJones: updated sparse_fls and added tau_api
4
+
5
+ """
6
+ clif.inverse
7
+ ~~~~~~~~~~~~
8
+ Fast, JIT-compiled multivector inverse routines for arbitrary signature.
9
+ """
10
+
11
+ from .fls import fls_inverse
12
+ from .newton import newton_schulz
13
+ from .euclidean import euclidean_inverse
14
+ from .sparse_fls import TauInverse
15
+ from .sparse_fls_dd import DDTauInverse
16
+ from .tau_api import get_inverter, inverse, warm
17
+ from .low_dim_inverse import inverse
18
+
19
+ __all__ = [
20
+ "euclidean_inverse",
21
+ "fls_inverse",
22
+ "newton_schulz",
23
+ "TauInverse",
24
+ "get_inverter", "inverse", "warm"
25
+ "inverse"
26
+ ]
@@ -0,0 +1,60 @@
1
+ # file: clif/inverse/euclidean.py
2
+ """
3
+ Top-level multivector inverse via the tau-domain kernel, d in 4-11.
4
+ """
5
+
6
+ import clif.context as Clif
7
+ from clif.multivector import Accum
8
+ from clif.inverse.tau_api import get_inverter
9
+ from clif.inverse.newton import newton_schulz
10
+
11
+
12
+ def euclidean_inverse(A: Accum, refine: bool = True) -> Accum:
13
+ """Inverse of a non-singular multivector in Euclidean Cl(d, 0), d in 6-13.
14
+
15
+ Uses the sparse FLS kernel for speed. At dimensions 12-13 the
16
+ polynomial iteration accumulates enough floating-point error that
17
+ the raw result has residuals of O(10⁻⁵) to O(10⁻³); when
18
+ ``refine=True`` (the default) Newton-Schulz iteration is applied
19
+ automatically to recover machine precision.
20
+
21
+ Parameters
22
+ ----------
23
+ A : Accum
24
+ Non-singular multivector.
25
+ refine : bool, optional
26
+ If True (default), apply Newton-Schulz refinement for dim >= 12.
27
+ Set False to return the raw FLS result at any dimension.
28
+
29
+ Returns
30
+ -------
31
+ Accum
32
+ Multiplicative inverse of A.
33
+
34
+ Raises
35
+ ------
36
+ ValueError
37
+ If dimension is outside 6-13.
38
+
39
+ Notes
40
+ -----
41
+ Typical residuals (max |A · A⁻¹ − e₀| over all blades):
42
+
43
+ ====== ============ ===============
44
+ dim FLS only FLS + NS
45
+ ====== ============ ===============
46
+ 6 1.4 × 10⁻¹⁴ —
47
+ 7 1.7 × 10⁻¹⁵ —
48
+ 8 2.4 × 10⁻¹⁴ —
49
+ 9 1.8 × 10⁻¹² —
50
+ 10 3.6 × 10⁻¹⁰ —
51
+ 11 2.9 × 10⁻¹⁰ —
52
+ 12 9.4 × 10⁻⁶ 9.0 × 10⁻¹⁶
53
+ 13 4.2 × 10⁻³ 1.8 × 10⁻¹⁵
54
+ ====== ============ ===============
55
+ """
56
+ X = Accum()
57
+ X.Reg = get_inverter(Clif.get_signature()).inverse(A.Reg)
58
+ if refine and A.dimensions >= 12:
59
+ X = newton_schulz(A, X)
60
+ return X