Beispiel #1
0
def log_sum(
    log_x: np.ndarray,
    offset: Optional[Union[Iterable[float], float]] = None
) -> Union[np.ndarray, float]:
    r"""
    Calculates the sum of a log vector or matrix.

    If the input array is a matrix, the sum is taken along the columns.

    Notes
    -----
    Given a vector, :math:`V`,

    .. math::

        V = [x_1, x_2, \dots, x_n]

    where :math:`x_i` is the log value at row :math:`i`, the function will calculate the sum of this vector. If data
    is a matrix, it will calculate the sum of the column vectors.


    Parameters
    ----------
    log_x
        a vector or matrix of log values

    offset
        the offset to subtract and re-add. This is done to avoid corner cases where the log values are extremely large

    Returns
    -------
    ndarray or float
        sum of log values
    """
    log_x = as_array(log_x)
    if log_x.ndim == 1:
        log_x = log_x.reshape(-1, 1)
    elif log_x.ndim > 2:
        raise ValueError("Input must be a vector or matrix.")

    if offset is None:
        offset = log_x.max(0)  # maximum from each column
    elif hasattr(offset, "__iter__"):
        offset = np.asarray(offset)
        assert len(
            offset) == log_x.shape[1], "Offset must match data dimensions"

    res = offset + np.log(np.exp(log_x - offset).sum(0))
    return res if len(res) > 1 else res[0]
Beispiel #2
0
def debye2(x):
    """
    Custom debye order 2 that takes care of negative numbers or non-finite numbers

    Parameters
    ----------
    x: array_like
        Numeric vector

    Returns
    -------
    ndarray or scalar
        Debye order 2 numbers

    See Also
    --------
    :code:`copulae.special.debye.debye_2`: The debye order 2 function
    """
    x = as_array(x)
    fin = np.isfinite(x)
    d = np.ravel(np.abs(x))

    with np.errstate(invalid='ignore'):
        if np.all(fin):
            d = debye_2(d)
        else:
            d[fin] = debye_2(d[fin])
            d = np.ravel(d)

            pinf = np.isposinf(x)
            if np.any(pinf):
                d[pinf] = 0  # set positive infinity to 0 (but not na, thus can't use ~fin)

        d = np.ravel(d)
        d[x < 0] -= 2 / 3 * x[x < 0]
        return d.item(0) if d.size == 1 else d