Repository: scipy/scipy
File: scipy/stats/_binomtest.py (Python)

Code before:
                                               correction=method == 'wilsoncc')
        return ConfidenceInterval(low=low, high=high)


def _binom_exact_conf_int(k, n, confidence_level, alternative):
    """
    Compute the estimate and confidence interval for the binomial test.

    Returns proportion, prop_low, prop_high
    """
    init = (0.0, 1.0)
    args = (k, n)
    alpha = ((1 - confidence_level) / 2 if alternative == 'two-sided'
             else 1 - confidence_level)

    plow = (np.zeros(k.shape, dtype=np.float64) if alternative == 'less' else
            find_root(lambda p, k, n: binom.sf(k-1, n, p) - alpha, init, args=args).x)
    phigh = (np.ones(k.shape, dtype=np.float64) if alternative == 'greater' else
             find_root(lambda p, k, n: binom.cdf(k, n, p) - alpha, init, args=args).x)

    plow = np.where(k == 0, 0.0, plow)
    phigh = np.where(k == n, 1.0, phigh)
    return plow, phigh


def _binom_wilson_conf_int(k, n, confidence_level, alternative, correction):
    # This function assumes that the arguments have already been validated.
    # In particular, `alternative` must be one of 'two-sided', 'less' or
    # 'greater'.
    p = k / n
    if alternative == 'two-sided':
        z = ndtri(0.5 + 0.5*confidence_level)
    else:
        z = ndtri(confidence_level)

    # For reference, the formulas implemented here are from
    # Newcombe (1998) (ref. [3] in the proportion_ci docstring).
    denom = 2*(n + z**2)
    center = (2*n*p + z**2)/denom
    q = 1 - p

    if correction:
        with np.errstate(divide='ignore', invalid='ignore'):
            dlo = (1 + z*np.sqrt(z**2 - 2 - 1/n + 4*p*(n * q + 1)))/denom
            dhi = (1 + z*np.sqrt(z**2 + 2 - 1/n + 4*p*(n * q - 1)))/denom
    else:
        delta = z / denom * np.sqrt(4 * n * p * q + z ** 2)
        dlo, dhi = delta, delta

    lo = np.where((k == 0) | (alternative == 'less'), 0.0, center - dlo)
    hi = np.where((k == n) | (alternative == 'greater'), 1.0, center + dhi)

Review comment (suggestion):
Could use `at.set` here with array API. Probably should test these explicitly.

Also need to make sure these and all other attributes are scalars for scalar input.

Code after:
                                               correction=method == 'wilsoncc')
        return ConfidenceInterval(low=low[()], high=high[()])


def _binom_exact_conf_int(k, n, confidence_level, alternative):
    """
    Compute the estimate and confidence interval for the binomial test.

    Returns proportion, prop_low, prop_high
    """
    init = (0.0, 1.0)
    args = (k, n)
    alpha = ((1 - confidence_level) / 2 if alternative == 'two-sided'
             else 1 - confidence_level)

    # I think using the private methods here is fine, since we will only evaluate with
    # valid `p`, `k`, and `n` (or all NaNs). One exception is when `k=0` and
    # `binom._sf(k-1, n, p)`: evaluates to NaN, but that's not a problem because
    # `plow` has a special case for `k=0` below.
    plow = (np.zeros(k.shape, dtype=np.float64) if alternative == 'less' else
            find_root(lambda p, k, n: binom._sf(k-1, n, p) - alpha, init, args=args).x)
    phigh = (np.ones(k.shape, dtype=np.float64) if alternative == 'greater' else
             find_root(lambda p, k, n: binom._cdf(k, n, p) - alpha, init, args=args).x)

    plow = np.where(k == 0, 0.0, plow)
    phigh = np.where(k == n, 1.0, phigh)
    return plow, phigh


def _binom_wilson_conf_int(k, n, confidence_level, alternative, correction):
    # This function assumes that the arguments have already been validated.
    # In particular, `alternative` must be one of 'two-sided', 'less' or
    # 'greater'.
    p = k / n
    if alternative == 'two-sided':
        z = ndtri(0.5 + 0.5*confidence_level)
    else:
        z = ndtri(confidence_level)

    # For reference, the formulas implemented here are from
    # Newcombe (1998) (ref. [3] in the proportion_ci docstring).
    denom = 2*(n + z**2)
    center = (2*n*p + z**2)/denom
    q = 1 - p

    if correction:
        with np.errstate(divide='ignore', invalid='ignore'):
            dlo = (1 + z*np.sqrt(z**2 - 2 - 1/n + 4*p*(n*q + 1)))/denom
            dhi = (1 + z*np.sqrt(z**2 + 2 - 1/n + 4*p*(n*q - 1)))/denom
    else:
        delta = z / denom * np.sqrt(4*n*p*q + z**2)