# Source code for clifford.taylor_expansions

```"""
.. currentmodule:: clifford.taylor_expansions

=====================================================
taylor_expansions (:mod:`clifford.taylor_expansions`)
=====================================================

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

[docs]@_numba_utils.njit
def exp(x, max_order=15):
r"""
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

[docs]@_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

[docs]@_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

[docs]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)

[docs]@_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

[docs]@_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

[docs]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)
```