def test_gmm_heterosedastic_direct(cov_data, debias):
    x, z, eps, sigma = cov_data
    k = len(x)
    nobs = x[0].shape[0]
    wm = HeteroskedasticWeightMatrix()
    w = wm.weight_matrix(x, z, eps, sigma=sigma)
    cov_est = GMMHeteroskedasticCovariance(x,
                                           z,
                                           eps,
                                           w,
                                           sigma=sigma,
                                           debiased=debias)
    xpz_wi_zpxi = _xpz_wi_zpxi(x, z, w)
    xpz = _xpz(x, z)
    wi = np.linalg.inv(w)
    xpz_wi = xpz @ wi
    ze = [z[i] * eps[:, i:i + 1] for i in range(k)]
    ze = np.concatenate(ze, 1)
    zeez = ze.T @ ze / nobs
    assert_allclose(zeez, cov_est._omega())

    direct = xpz_wi_zpxi @ (xpz_wi @ zeez @ xpz_wi.T) @ xpz_wi_zpxi / nobs
    direct = (direct + direct.T) / 2
    if debias:
        df = [vx.shape[1] * np.ones(vx.shape[1]) for vx in x]
        df = np.concatenate(df)[:, None]
        df = np.sqrt(df)
        adj = nobs / (nobs - df @ df.T)
        direct *= adj
    direct = (direct + direct.T) / 2
    assert_allclose(direct, cov_est.cov)
def test_heteroskedastic_weight_direct(weight_data, center, debias):
    wm = HeteroskedasticWeightMatrix(center, debias)
    x, z, eps, sigma = weight_data
    weights = wm.weight_matrix(x, z, eps, sigma=sigma)
    k = len(z)
    ze = [z[i] * eps[:, i : i + 1] for i in range(k)]
    ze = np.concatenate(ze, 1)
    if center:
        ze = ze - ze.mean(0)
    nobs = ze.shape[0]
    direct = ze.T @ ze / nobs
    if debias:
        df = [vx.shape[1] * np.ones(vz.shape[1]) for vx, vz in zip(x, z)]
        df = np.concatenate(df)[:, None]
        df = np.sqrt(df)
        adj = nobs / (nobs - df @ df.T)
        direct *= adj
    assert_allclose(weights, direct)