Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions kingdon/numerical.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
def exp(x, n=10):
"""
Compute the exponential function using Taylor series expansion.

Uses incremental term computation for improved numerical stability and performance.

:param x: The input value (scalar or multivector).
:param n: Number of terms in the Taylor series (default: 10).
:return: Approximation of exp(x).
"""
result = 1.0
term = 1.0
for k in range(1, n):
term *= x / k
result += term
return result


def is_close(a, b, tol=1e-6):
"""
Check if two multivectors are close within tolerance.

Handles comparison of multivectors with potentially different sparse representations.

:param a: First multivector or scalar value.
:param b: Second multivector or scalar value.
:param tol: Tolerance for comparison (default: 1e-6).
:return: True if a and b are close within tolerance, False otherwise.
"""
if hasattr(a, 'keys') and hasattr(b, 'keys'):
all_keys = set(a.keys()) | set(b.keys())
for key in all_keys:
val_a = a.e if key == 0 else getattr(a, a.algebra.bin2canon[key], 0) if key in a.keys() else 0
val_b = b.e if key == 0 else getattr(b, b.algebra.bin2canon[key], 0) if key in b.keys() else 0
if abs(val_a - val_b) >= tol:
return False
return True
else:
return abs(a - b) < tol
14 changes: 14 additions & 0 deletions tests/test_kingdon.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
from sympy import Symbol, expand, sympify, cos, sin, sinc
from kingdon import Algebra, MultiVector, symbols
from kingdon.operator_dict import UnaryOperatorDict
from kingdon.numerical import exp as numerical_exp, is_close

import timeit

Expand Down Expand Up @@ -881,6 +882,19 @@ def test_simple_exp():
l = (-(B | B).e) ** 0.5
assert R == cos(l) + sinc(l) * B

def test_numerical_exp_simple_bivector(sta):
"""Test numerical.exp() on a simple bivector matches MultiVector.exp()"""
B = sta.bivector([1.0, 0, 0, 0, 0, 0])
mv_exp = B.exp()
num_exp = numerical_exp(B, n=20)
assert is_close(mv_exp, num_exp, tol=1e-10)

def test_numerical_exp_non_simple_bivector(sta):
"""Test numerical.exp() on a non-simple bivector doesn't raise an error"""
B = sta.bivector([1.0, 2.0, 0, 0, 0, 0])
result = numerical_exp(B, n=20)
assert result is not None

def test_dual_numbers():
alg = Algebra(r=1)
x = alg.multivector(name='x')
Expand Down