# Path: yatsm/accel.py
# @_doublewrap
# def try_jit(f, *args, **kwargs):
#     """ Apply numba.jit to function ``f`` if Numba is available
# 
#     Accepts arguments to Numba jit function (signature, nopython, etc.).
# 
#     Examples:
# 
#     .. code-block:: python
# 
#         @try_jit
#         @try_jit()
#         @try_jit(nopython=True)
#         @try_jit("float32[:](float32[:], float32[:])", nopython=True)
# 
#     """
#     if has_numba:
#         @wraps(f)
#         def wrap(*args, **kwargs):
#             return nb.jit(*args, **kwargs)
#         return wrap(f, *args, **kwargs)
#     else:
#         return f


import numpy as np
import sklearn
from yatsm.accel import try_jit

Run this file to test performance gains. Implementation is ~3x faster than
statsmodels and can reach ~4x faster if Numba is available to accelerate.

"""


EPS = np.finfo('float').eps


# Weight scaling methods
@try_jit(nopython=True)
def bisquare(resid, c=4.685):
    """
    Returns weighting for each residual using bisquare weight function

    Args:
        resid (np.ndarray): residuals to be weighted
        c (float): tuning constant for Tukey's Biweight (default: 4.685)

    Returns:
        weight (ndarray): weights for residuals

    Reference:
        http://statsmodels.sourceforge.net/stable/generated/statsmodels.robust.norms.TukeyBiweight.html
    """
    # Weight where abs(resid) < c; otherwise 0
    return (np.abs(resid) < c) * (1 - (resid / c) ** 2) ** 2



# Path: yatsm/accel.py
# @_doublewrap
# def try_jit(f, *args, **kwargs):
#     """ Apply numba.jit to function ``f`` if Numba is available
# 
#     Accepts arguments to Numba jit function (signature, nopython, etc.).
# 
#     Examples:
# 
#     .. code-block:: python
# 
#         @try_jit
#         @try_jit()
#         @try_jit(nopython=True)
#         @try_jit("float32[:](float32[:], float32[:])", nopython=True)
# 
#     """
#     if has_numba:
#         @wraps(f)
#         def wrap(*args, **kwargs):
#             return nb.jit(*args, **kwargs)
#         return wrap(f, *args, **kwargs)
#     else:
#         return f


# Path: yatsm/regression/robust_fit.py
import numpy as np
import sklearn
from yatsm.accel import try_jit


Run this file to test performance gains. Implementation is ~3x faster than
statsmodels and can reach ~4x faster if Numba is available to accelerate.

"""


EPS = np.finfo('float').eps


# Weight scaling methods
@try_jit(nopython=True)
def bisquare(resid, c=4.685):
    """
    Returns weighting for each residual using bisquare weight function

    Args:
        resid (np.ndarray): residuals to be weighted
        c (float): tuning constant for Tukey's Biweight (default: 4.685)

    Returns:
        weight (ndarray): weights for residuals

    Reference:
        http://statsmodels.sourceforge.net/stable/generated/statsmodels.robust.norms.TukeyBiweight.html
    """
    # Weight where abs(resid) < c; otherwise 0
    return (np.abs(resid) < c) * (1 - (resid / c) ** 2) ** 2



@try_jit(nopython=True)