def null_to_Nister_solution(X: torch.Tensor, batch_size: int) -> torch.Tensor:
    r"""Use Nister's 5PC to solve essential matrix.

    The linear system is solved by Nister's 5-point algorithm [@nister2004efficient],
    and the solver implemented referred to [@barath2020magsac++][@wei2023generalized][@wang2023vggsfm].

    Args:
        X: Coefficients for the null space :math:`(B, N, 2), N>=8`.
        batch_size: batcs size of the input, the number of image pairs :math:`B`.

    Returns:
        the computed essential matrix with shape :math:`(B, 3, 3)`.
        Note that the returned E matrices should be the same batch size with the input.

    """
    # compute eigenvectors and retrieve the one with the smallest eigenvalue, using SVD
    # turn off the grad check due to the unstable gradients from SVD.
    # several close to zero values of eigenvalues.
    _, _, V = _torch_svd_cast(X)  # torch.svd

    null_ = V[:, :, -4:]  # the last four rows
    nullSpace = V.transpose(-1, -2)[:, -4:, :]

    coeffs = zeros(batch_size, 10, 20, device=null_.device, dtype=null_.dtype)
    d = zeros(batch_size, 60, device=null_.device, dtype=null_.dtype)

    # Determinant constraint
    coeffs[:, 9] = (
        solvers.multiply_deg_two_one_poly(
            solvers.multiply_deg_one_poly(fun_select(null_, 0, 1), fun_select(null_, 1, 2))
            - solvers.multiply_deg_one_poly(fun_select(null_, 0, 2), fun_select(null_, 1, 1)),
            fun_select(null_, 2, 0),
        )
        + solvers.multiply_deg_two_one_poly(
            solvers.multiply_deg_one_poly(fun_select(null_, 0, 2), fun_select(null_, 1, 0))
            - solvers.multiply_deg_one_poly(fun_select(null_, 0, 0), fun_select(null_, 1, 2)),
            fun_select(null_, 2, 1),
        )
        + solvers.multiply_deg_two_one_poly(
            solvers.multiply_deg_one_poly(fun_select(null_, 0, 0), fun_select(null_, 1, 1))
            - solvers.multiply_deg_one_poly(fun_select(null_, 0, 1), fun_select(null_, 1, 0)),
            fun_select(null_, 2, 2),
        )
    )

    indices = torch.tensor([[0, 10, 20], [10, 40, 30], [20, 30, 50]])

    # Compute EE^T (Eqn. 20 in the paper)
    for i in range(3):
        for j in range(3):
            d[:, indices[i, j] : indices[i, j] + 10] = (
                solvers.multiply_deg_one_poly(fun_select(null_, i, 0), fun_select(null_, j, 0))
                + solvers.multiply_deg_one_poly(fun_select(null_, i, 1), fun_select(null_, j, 1))
                + solvers.multiply_deg_one_poly(fun_select(null_, i, 2), fun_select(null_, j, 2))
            )

    for i in range(10):
        t = 0.5 * (d[:, indices[0, 0] + i] + d[:, indices[1, 1] + i] + d[:, indices[2, 2] + i])
        d[:, indices[0, 0] + i] -= t
        d[:, indices[1, 1] + i] -= t
        d[:, indices[2, 2] + i] -= t

    cnt = 0
    for i in range(3):
        for j in range(3):
            row = (
                solvers.multiply_deg_two_one_poly(d[:, indices[i, 0] : indices[i, 0] + 10], fun_select(null_, 0, j))
                + solvers.multiply_deg_two_one_poly(d[:, indices[i, 1] : indices[i, 1] + 10], fun_select(null_, 1, j))
                + solvers.multiply_deg_two_one_poly(d[:, indices[i, 2] : indices[i, 2] + 10], fun_select(null_, 2, j))
            )
            coeffs[:, cnt] = row
            cnt += 1

    b = coeffs[:, :, 10:]
    singular_filter = torch.linalg.matrix_rank(coeffs[:, :, :10]) >= torch.max(
        torch.linalg.matrix_rank(coeffs), ones_like(torch.linalg.matrix_rank(coeffs[:, :, :10])) * 10
    )

    # check if there is no solution
    if singular_filter.sum() == 0:
        return torch.eye(3, dtype=coeffs.dtype, device=coeffs.device)[None].expand(batch_size, 10, -1, -1).clone()

    eliminated_mat = _torch_solve_cast(coeffs[singular_filter, :, :10], b[singular_filter])

    coeffs_ = torch.cat((coeffs[singular_filter, :, :10], eliminated_mat), dim=-1)

    # check the batch size after singular filter, for batch operation afterwards
    batch_size_filtered = coeffs_.shape[0]

    A = zeros(coeffs_.shape[0], 3, 13, device=coeffs_.device, dtype=coeffs_.dtype)

    for i in range(3):
        A[:, i, 0] = 0.0
        A[:, i : i + 1, 1:4] = coeffs_[:, 4 + 2 * i : 5 + 2 * i, 10:13]
        A[:, i : i + 1, 0:3] -= coeffs_[:, 5 + 2 * i : 6 + 2 * i, 10:13]
        A[:, i, 4] = 0.0
        A[:, i : i + 1, 5:8] = coeffs_[:, 4 + 2 * i : 5 + 2 * i, 13:16]
        A[:, i : i + 1, 4:7] -= coeffs_[:, 5 + 2 * i : 6 + 2 * i, 13:16]
        A[:, i, 8] = 0.0
        A[:, i : i + 1, 9:13] = coeffs_[:, 4 + 2 * i : 5 + 2 * i, 16:20]
        A[:, i : i + 1, 8:12] -= coeffs_[:, 5 + 2 * i : 6 + 2 * i, 16:20]

    # Bx11
    cs = solvers.determinant_to_polynomial(A)

    # A: Bx3x13
    # nullSpace: Bx4x9
    # companion matrices to solve the polynomial, in batch
    C = zeros((batch_size_filtered, 10, 10), device=cs.device, dtype=cs.dtype)
    eye_mat = eye(C[0, 0:-1, 0:-1].shape[0], device=cs.device, dtype=cs.dtype)
    C[:, 0:-1, 1:] = eye_mat

    cs_de = cs[:, -1].unsqueeze(-1)
    cs_de = torch.where(cs_de == 0, torch.tensor(1e-8, dtype=cs_de.dtype), cs_de)
    C[:, -1, :] = -cs[:, :-1] / cs_de

    roots = torch.real(torch.linalg.eigvals(C))

    roots_unsqu = roots.unsqueeze(1)

    Bs = stack(
        (
            A[:, :3, :1] * (roots_unsqu**3)
            + A[:, :3, 1:2] * roots_unsqu.square()
            + A[:, 0:3, 2:3] * roots_unsqu
            + A[:, 0:3, 3:4],
            A[:, 0:3, 4:5] * (roots_unsqu**3)
            + A[:, 0:3, 5:6] * roots_unsqu.square()
            + A[:, 0:3, 6:7] * roots_unsqu
            + A[:, 0:3, 7:8],
        ),
        dim=1,
    )

    Bs = Bs.transpose(1, -1)

    bs = (
        (
            A[:, 0:3, 8:9] * (roots_unsqu**4)
            + A[:, 0:3, 9:10] * (roots_unsqu**3)
            + A[:, 0:3, 10:11] * roots_unsqu.square()
            + A[:, 0:3, 11:12] * roots_unsqu
            + A[:, 0:3, 12:13]
        )
        .transpose(1, 2)
        .unsqueeze(-1)
    )

    xzs = torch.matmul(torch.inverse(Bs[:, :, 0:2, 0:2]), bs[:, :, 0:2])

    mask = (abs(Bs[:, 2].unsqueeze(1) @ xzs - bs[:, 2].unsqueeze(1)) > 1e-3).flatten()

    # mask: bx10x1x1
    mask = (
        abs(torch.matmul(Bs[:, :, 2, :].unsqueeze(2), xzs) - bs[:, :, 2, :].unsqueeze(2)) > 1e-3
    )  # .flatten(start_dim=1)

    # bx10
    mask = mask.squeeze(3).squeeze(2)

    if torch.any(mask):
        q_batch, r_batch = torch.linalg.qr(Bs[mask])
        xyz_to_feed = torch.linalg.solve(r_batch, torch.matmul(q_batch.transpose(-1, -2), bs[mask]))
        xzs[mask] = xyz_to_feed

    nullSpace_filtered = nullSpace[singular_filter]

    Es = (
        nullSpace_filtered[:, 0:1] * (-xzs[:, :, 0])
        + nullSpace_filtered[:, 1:2] * (-xzs[:, :, 1])
        + nullSpace_filtered[:, 2:3] * roots.unsqueeze(-1)
        + nullSpace_filtered[:, 3:4]
    )

    inv = 1.0 / torch.sqrt((-xzs[:, :, 0]) ** 2 + (-xzs[:, :, 1]) ** 2 + roots.unsqueeze(-1) ** 2 + 1.0)
    Es *= inv

    Es = Es.view(batch_size_filtered, -1, 3, 3).transpose(-1, -2)

    # make sure the returned batch size equals to that of inputs
    E_return = torch.eye(3, dtype=Es.dtype, device=Es.device)[None].expand(batch_size, 10, -1, -1).clone()
    E_return[singular_filter] = Es

    return E_return
Use Nister's 5PC to solve essential matrix.

    The linear system is solved by Nister's 5-point algorithm [@nister2004efficient],
    and the solver implemented referred to [@barath2020magsac++][@wei2023generalized][@wang2023vggsfm].

    Args:
        X: Coefficients for the null space :math:`(B, N, 2), N>=8`.
        batch_size: batcs size of the input, the number of image pairs :math:`B`.

    Returns:
        the computed essential matrix with shape :math:`(B, 3, 3)`.
        Note that the returned E matrices should be the same batch size with the input.

    
kornia/geometry/epipolar/essential.py