Source code for shenfun.optimization
"""Module for optimized functions
Some methods performed in Python may be slowing down solvers. In this optimization
module we place optimized functions that are to be used instead of default
Python methods. Some methods are implemented solely in Cython and only called
from within the regular Python modules.
"""
import importlib
from functools import wraps
from shenfun.config import config
try:
from . import cython
except ModuleNotFoundError:
cython = None
#try:
from . import numba
#except ModuleNotFoundError:
# numba = None
"""
runtimeoptimizer
A decorator that chooses optimized function at runtime
At runtime the decorator looks at::
config['optimization']['mode']
config['optimization']['verbose']
and returns the optimized function of choice.
"""
[docs]
class runtimeoptimizer:
def __init__(self, func):
self.func = func
self.__doc__ = func.__doc__
def __call__(self, *args, **kwargs):
fun = optimizer(self.func)
return fun(*args, **kwargs)
[docs]
def optimizer(func, wrap=True):
"""Decorator used to wrap calls to optimized versions of functions.
The optimized version must be implemented in the cython or numba modules.
For example, the :class:`.la.TDMA` linear algebra solver has a method called
:meth:`~shenfun.la.TDMA.Solve`, which is implemented with faster (optimized) code in
:meth:`~shenfun.optimization.cython.la.TDMA_Solve` and
:meth:`~shenfun.optimization.numba.tdma.TDMA_Solve`.
Parameters
----------
func : The function to optimize
wrap : bool, optional
If True, return function wrapped using functools wraps.
If False, return unwrapped function.
"""
mod = config['optimization']['mode']
verbose = config['optimization']['verbose']
if mod.lower() not in ('cython', 'numba'):
# Use python function
if verbose:
print(func.__qualname__ + ' not optimized')
return func
mod = {'cython': cython, 'numba': numba}[mod.lower()]
fun = getattr(mod, func.__name__, func)
if fun is func:
fun = getattr(mod, func.__qualname__.replace('.', '_'), func)
if verbose:
if fun is func:
print(fun.__qualname__ + ' not optimized')
if wrap is False:
return fun
@wraps(func)
def wrapped_function(*args, **kwargs):
u0 = fun(*args, **kwargs)
return u0
return wrapped_function