fn line_naive(p: &G1Point, t: &G2Point, q: &G2Point) -> Fp12E {
    let [x_p, y_p, _] = p.coordinates();

    if t == q {
        let b = t.y().square();
        let c = t.z().square();
        let e = BN254TwistCurve::b() * (c.double() + &c);
        let h = (t.y() + t.z()).square() - (&b + &c);
        let i = &e - &b;
        let j = t.x().square();

        // We are transforming one representation of Fp12 into another:
        // If f in Fp12, then f = g + h * w = g0 + h0 * w + g1 * w^2 + h1 * w^3 + g2 * w^4 + h2 * w^5,
        // where g = g0 + g1 * v + g2 * v^2,
        // and h = h0 + h1 * v + h2 * v^2.
        // See https://hackmd.io/@Wimet/ry7z1Xj-2#Tower-of-Extension-Fields.
        Fp12E::new([
            Fp6E::new([y_p * (-h), Fp2E::zero(), Fp2E::zero()]),
            Fp6E::new([x_p * (j.double() + &j), i, Fp2E::zero()]),
        ])
    } else {
        let [x_q, y_q, _] = q.coordinates();

        let theta = t.y() - (y_q * t.z());
        let lambda = t.x() - (x_q * t.z());
        let j = &theta * x_q - (&lambda * y_q);

        Fp12E::new([
            Fp6E::new([y_p * lambda, Fp2E::zero(), Fp2E::zero()]),
            Fp6E::new([x_p * (-theta), j, Fp2E::zero()]),
        ])
    }
}
Depending on the case, it computes the tangent line of t or the line
between t and q evaluated in p.
Algorithm adapted from Arkowork's double_in_place and add_in_place.
See https://github.com/arkworks-rs/algebra/blob/master/ec/src/models/bn/g2.rs#L25.
See https://eprint.iacr.org/2013/722.pdf (Page 13, Equations 11 and 13).
crates/math/src/elliptic_curve/short_weierstrass/curves/bn_254/pairing.rs