Given bins (S) and b (N) solve for MLE of truncated logseries
    parameter p

    Parameters
    -----------
    bins : float
        Number of bins. Considered S in an ecological context
    b : float
        Upper truncation of distribution. Considered N in an ecological context

    Returns
    -------
    : float
        MLE estimate of p

    Notes
    ------
    Adapted from Ethan White's macroecology_tools

def _trunc_logser_solver(bins, b):
    """
    Given bins (S) and b (N) solve for MLE of truncated logseries
    parameter p

    Parameters
    -----------
    bins : float
        Number of bins. Considered S in an ecological context
    b : float
        Upper truncation of distribution. Considered N in an ecological context

    Returns
    -------
    : float
        MLE estimate of p

    Notes
    ------
    Adapted from Ethan White's macroecology_tools
    """

    if bins == b:
        p = 0

    else:
        BOUNDS = [0, 1]
        DIST_FROM_BOUND = 10 ** -15
        m = np.array(np.arange(1, np.int(b) + 1))
        y = lambda x: np.sum(x ** m / b * bins) - np.sum((x ** m) / m)
        p = optim.bisect(y, BOUNDS[0] + DIST_FROM_BOUND,
                   min((sys.float_info[0] / bins) ** (1 / b), 2),
                   xtol=1.490116e-08, maxiter=1000)
    return p