Log of the sum of the exp of the arguments. 

    Parameters
    ----------
    v: ndarray

    Returns
    -------
    l: float 
        l = log(sum(exp(v)))

    Note
    ----
    use the log_sum_exp trick to avoid overflow: i.e. we remove the max of v
    before exponentiating, then we add it back

    See also
    --------
    log_mean_exp

def log_sum_exp(v):
    """Log of the sum of the exp of the arguments. 

    Parameters
    ----------
    v: ndarray

    Returns
    -------
    l: float 
        l = log(sum(exp(v)))

    Note
    ----
    use the log_sum_exp trick to avoid overflow: i.e. we remove the max of v
    before exponentiating, then we add it back

    See also
    --------
    log_mean_exp

    """
    m = v.max()
    return m + np.log(np.sum(np.exp(v - m)))