def exp_sample(scale, nscale):
    u_max = 1. / scale * (1 - np.exp(-nscale))
    npoint = sph_bessel.pow_2_gt(4 * nscale) + 1
    delta_u = u_max / (npoint - 1)
    u = np.linspace(0, u_max, npoint, endpoint=True)

    x = -1. / scale * np.log(1 - scale * u)
    return x, delta_u
def local_term(ells, chi, delta, flat=False):
    
    out = []
    chi = float(chi)
    delta = float(delta)

    for ell in ells:
        ell = int(ell)
        p_k_interp = matter_power.p_k_interp(chi)

        if flat:
            if (ell/chi) > matter_power.K_MAX:
                out.append(0.)
                continue
            # Maximum k_par.
            k_max = np.sqrt(max(matter_power.K_MAX**2 - (ell/chi)**2, 0))
            # Reduce x_max if envelope is significant.
            if delta == 0:
                envelop_width = 1000 * k_max
            else:
                envelop_width = 5 * (2 * np.pi / delta)
            k_max = min(k_max, 5 * envelop_width)

            nk = sph_bessel.pow_2_gt(k_max * delta * 5) + 1
            k = np.linspace(0, k_max, nk, endpoint=True)

            delta_k = k_max / (nk - 1)
            
            # Envelope of a Gaussian with width of several oscillations. This
            # controls the oscillations out to high k.
            envelope = np.exp(-0.5*k**2 / envelop_width**2)

            p_k_local = p_k_interp(np.sqrt((ell/chi)**2 + k**2))
            p_k_local *= envelope
            # Fourier factor.
            p_k_local *= np.cos(k * delta)

            I1 = integrate.romb(p_k_local, dx=delta_k)
            I1 /= np.pi * chi**2
        else:
            p_k = lambda k: k**2 * p_k_interp(k)
            I1 = sph_bessel.integrate_f_jnjn(p_k, ell, chi, delta,
                    matter_power.K_MAX) * (2 / np.pi)
        out.append(I1)
    return out