Repository: scipy/scipy
File: scipy/integrate/_quadrature.py (Python)

Code before:
    else:
        BN = N/(N+2.)
        power = N+1

    BN = BN - np.dot(yi**power, ai)
    p1 = power+1
    fac = power*math.log(N) - gammaln(p1)
    fac = math.exp(fac)
    return ai, BN*fac


def _qmc_quad_iv(func, a, b, n_points, n_estimates, qrng, log, xp):
    a, b = xp_promote(a, b, broadcast=True, force_floating=True, xp=xp)

    # lazy import to avoid issues with partially-initialized submodule
    if not hasattr(qmc_quad, 'qmc'):
        from scipy import stats
        qmc_quad.stats = stats
    else:
        stats = qmc_quad.stats

    if not callable(func):
        message = "`func` must be callable."
        raise TypeError(message)

    # a, b will be modified, so copy. Oh well if it's copied twice.
    a = xpx.atleast_nd(a, ndim=1, xp=xp)
    b = xpx.atleast_nd(b, ndim=1, xp=xp)
    a, b = xp.broadcast_arrays(a, b)
    a, b = xp_copy(a), xp_copy(b)
    dim = a.shape[0]

    try:
        func((a + b) / 2)
    except Exception as e:
        message = ("`func` must evaluate the integrand at points within "
                   "the integration range; e.g. `func( (a + b) / 2)` "
                   "must return the integrand at the centroid of the "
                   "integration volume.")
        raise ValueError(message) from e

    try:
        func(xp.stack([a, b]).T)
        vfunc = func
    except Exception as e:
        if not is_numpy(xp):
            message = ("Exception encountered when attempting vectorized call to "
                       f"`func`: {e}. When using array library {xp}, `func` must "
                       "accept two-dimensional array `x` with shape `(a.shape[0], "
                       "n_points)` and return an array of the integrand value at "
                       "each of the `n_points`.")

Review comment (suggestion):
```suggestion
    a, b = xp_promote(a, b, broadcast=True, force_floating=True, xp=xp)
    a = xpx.atleast_nd(a, ndim=1, xp=xp)
```

Code after:
    else:
        BN = N/(N+2.)
        power = N+1

    BN = BN - np.dot(yi**power, ai)
    p1 = power+1
    fac = power*math.log(N) - gammaln(p1)
    fac = math.exp(fac)
    return ai, BN*fac


def _qmc_quad_iv(func, a, b, n_points, n_estimates, qrng, log, xp):
    # lazy import to avoid issues with partially-initialized submodule
    if not hasattr(qmc_quad, 'qmc'):
        from scipy import stats
        qmc_quad.stats = stats
    else:
        stats = qmc_quad.stats

    if not callable(func):
        message = "`func` must be callable."
        raise TypeError(message)

    # a, b will be modified, so copy. Oh well if it's copied twice.
    a, b = xp_promote(a, b, broadcast=True, force_floating=True, xp=xp)
    a = xpx.atleast_nd(a, ndim=1, xp=xp)
    b = xpx.atleast_nd(b, ndim=1, xp=xp)
    a, b = xp.broadcast_arrays(a, b)
    a, b = xp_copy(a), xp_copy(b)
    dim = a.shape[0]

    try:
        func((a + b) / 2)
    except Exception as e:
        message = ("`func` must evaluate the integrand at points within "
                   "the integration range; e.g. `func( (a + b) / 2)` "
                   "must return the integrand at the centroid of the "
                   "integration volume.")
        raise ValueError(message) from e

    try:
        func(xp.stack([a, b]).T)
        vfunc = func
    except Exception as e:
        if not is_numpy(xp):
            message = ("Exception encountered when attempting vectorized call to "
                       f"`func`: {e}. When using array library {xp}, `func` must "
                       "accept two-dimensional array `x` with shape `(a.shape[0], "
                       "n_points)` and return an array of the integrand value at "
                       "each of the `n_points`.")
            raise ValueError(message)