-
Notifications
You must be signed in to change notification settings - Fork 73
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add a new clifford.taylor_expansions module (#371)
This contains series expansions of trigonometric, exponential, and hyperbolic functions. This also tweaks the implementation of the hitzer inverse to behave slightly better on degenerate algebras, and fixes a crash when computing an inverse in `Cl(0, 0, 0)`. `cf.general_exp(mv)` has been deprecated in favor of `cf.taylor_expansions.exp(mv)`, or the more convenient spelling `mv.exp()`. The new function is jitted, unlike the old one. Finally, this overloads pow in numba to allow it to be used in jitted code.
- Loading branch information
1 parent
ddbf8d7
commit 1b56672
Showing
9 changed files
with
301 additions
and
43 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,164 @@ | ||
""" | ||
.. currentmodule:: clifford.taylor_expansions | ||
===================================================== | ||
taylor_expansions (:mod:`clifford.taylor_expansions`) | ||
===================================================== | ||
.. versionadded:: 1.4.0 | ||
This file implements various Taylor expansions for useful functions of multivectors. | ||
For some algebra signatures there may exist closed forms of these functions which would likely be faster | ||
and more accurate. Nonetheless, having pre-written taylor expansions for the general case is useful. | ||
.. note:: | ||
Many of these functions are also exposed as :class:`~clifford.MultiVector` methods, | ||
such as :meth:`clifford.MultiVector.sin`. This means that ``mv.sin()`` or even ``np.sin(mv)`` can be used | ||
as a convenient interface to functions in this module, without having to import it directly. | ||
For example:: | ||
>>> from clifford.g3 import * | ||
>>> import numpy as np | ||
>>> np.sin(np.pi*e12/4) | ||
(0.86867^e12) | ||
Implemented functions | ||
---------------- | ||
.. autofunction:: exp | ||
.. autofunction:: sin | ||
.. autofunction:: cos | ||
.. autofunction:: tan | ||
.. autofunction:: sinh | ||
.. autofunction:: cosh | ||
.. autofunction:: tanh | ||
""" | ||
import math | ||
import numpy as np | ||
|
||
from . import _numba_utils | ||
from . import _settings | ||
|
||
|
||
@_numba_utils.njit | ||
def exp(x, max_order=15): | ||
""" | ||
This implements the series expansion of :math:`\exp x` where :math:`x` is a multivector | ||
The parameter `max_order` is the maximum order of the taylor series to use | ||
""" | ||
|
||
result = 1.0 + 0.0*x | ||
if max_order == 0: | ||
return result | ||
|
||
# scale by power of 2 so that its norm is < 1 | ||
max_val = int(np.max(np.abs(x.value))) | ||
scale = 1 | ||
if max_val > 1: | ||
max_val <<= 1 | ||
while max_val: | ||
max_val >>= 1 | ||
scale <<= 1 | ||
|
||
scaled = x * (1.0 / scale) | ||
|
||
# taylor approximation | ||
tmp = 1.0 + 0.0*x | ||
for i in range(1, max_order): | ||
if np.any(np.abs(tmp.value) > _settings._eps): | ||
tmp = tmp*scaled * (1.0 / i) | ||
result = result + tmp | ||
else: | ||
break | ||
|
||
# undo scaling | ||
while scale > 1: | ||
result = result*result | ||
scale >>= 1 | ||
return result | ||
|
||
|
||
@_numba_utils.njit | ||
def sin(X, max_order=30): | ||
""" | ||
A taylor series expansion for sin | ||
The parameter `max_order` is the maximum order of the taylor series to use | ||
""" | ||
op = +X | ||
X2 = X*X | ||
X2np1 = X | ||
for n in range(1, max_order): | ||
X2np1 = X2np1 * X2 | ||
op = op + ((-1) ** (n) / math.gamma(2 * n + 2)) * X2np1 | ||
return op | ||
|
||
|
||
@_numba_utils.njit | ||
def cos(X, max_order=30): | ||
""" | ||
A taylor series expansion for cos | ||
The parameter `max_order` is the maximum order of the taylor series to use | ||
""" | ||
op = 1 + 0*X | ||
X2 = X * X | ||
X2n = 1 + 0*X | ||
for n in range(1, max_order): | ||
X2n = X2n*X2 | ||
op = op + ((-1) ** (n) / math.gamma(2 * n + 1)) * X2n | ||
return op | ||
|
||
|
||
def tan(X, max_order=30): | ||
""" | ||
The tan function as the ratio of sin and cos | ||
The parameter `max_order` is the maximum order of the taylor series to use | ||
.. note:: | ||
It would probably be better to implement this as its own taylor series. This function | ||
is not JITed as currently we do not overload the truediv operator for multivectors. | ||
""" | ||
return sin(X, max_order) / cos(X, max_order) | ||
|
||
|
||
@_numba_utils.njit | ||
def sinh(X, max_order=30): | ||
""" | ||
A taylor series expansion for sinh | ||
The parameter `max_order` is the maximum order of the taylor series to use | ||
""" | ||
op = +X | ||
X2 = X * X | ||
X2np1 = X | ||
for n in range(1, max_order): | ||
X2np1 = X2np1 * X2 | ||
op = op + (1 / math.gamma(2 * n + 2)) * X2np1 | ||
return op | ||
|
||
|
||
@_numba_utils.njit | ||
def cosh(X, max_order=30): | ||
""" | ||
A taylor series expansion for cosh | ||
The parameter `max_order` is the maximum order of the taylor series to use | ||
""" | ||
op = 1 + 0 * X | ||
X2 = X * X | ||
X2n = 1 + 0 * X | ||
for n in range(1, max_order): | ||
X2n = X2n * X2 | ||
op = op + (1 / math.gamma(2 * n + 1)) * X2n | ||
return op | ||
|
||
|
||
def tanh(X, max_order=30): | ||
""" | ||
The tanh function as the ratio of sinh and cosh | ||
The parameter `max_order` is the maximum order of the taylor series to use | ||
.. note:: | ||
It would probably be better to implement this as its own taylor series. This function | ||
is not JITed as currently we do not overload the truediv operator for multivectors. | ||
""" | ||
return sinh(X, max_order) / cosh(X, max_order) |
Oops, something went wrong.