void Tate3_pairings()

in src/compression/pairing.c [49:153]


void Tate3_pairings(point_full_proj_t *Qj, f2elm_t* f)
{
    felm_t *x, *y, *l1, *l2, *n1, *n2, *x2, *x23, *x2p3;
    f2elm_t xQ2s[t_points], finv[2*t_points], one = {0};
    f2elm_t t0, t1, t2, t3, t4, t5, g, h, tf;

    fpcopy((digit_t*)&Montgomery_one, one[0]);

    for (int j = 0; j < t_points; j++) {
        fp2copy(one, f[j]);
        fp2copy(one, f[j+t_points]);
        fp2sqr_mont(Qj[j]->X, xQ2s[j]);
    }

    for (int k = 0; k < OBOB_EXPON - 1; k++) {
        l1   = (felm_t*)T_tate3 + 6*k + 0;
        l2   = (felm_t*)T_tate3 + 6*k + 1;
        n1   = (felm_t*)T_tate3 + 6*k + 2;
        n2   = (felm_t*)T_tate3 + 6*k + 3;
        x23  = (felm_t*)T_tate3 + 6*k + 4;
        x2p3 = (felm_t*)T_tate3 + 6*k + 5;
        for (int j = 0; j < t_points; j++) {
            fpmul_mont(Qj[j]->X[0], *l1, t0[0]);
            fpmul_mont(Qj[j]->X[1], *l1, t0[1]);
            fpmul_mont(Qj[j]->X[0], *l2, t2[0]);
            fpmul_mont(Qj[j]->X[1], *l2, t2[1]);
            fpadd(xQ2s[j][0], *x23, t4[0]);
            fpcopy(xQ2s[j][1], t4[1]);
            fpmul_mont(Qj[j]->X[0], *x2p3, t5[0]);
            fpmul_mont(Qj[j]->X[1], *x2p3, t5[1]);

            fp2sub(t0, Qj[j]->Y, t1);
            fpadd(t1[0], *n1, t1[0]);
            fp2sub(t2, Qj[j]->Y, t3);
            fpadd(t3[0], *n2, t3[0]);
            fp2mul_mont(t1, t3, g);
            fp2sub(t4, t5, h);
            fp2_conj(h, h);
            fp2mul_mont(g, h, g);

            fp2sqr_mont(f[j], tf);
            fp2mul_mont(f[j], tf, f[j]);
            fp2mul_mont(f[j], g, f[j]);

            fpsub(t0[1], Qj[j]->Y[0], t1[0]);
            fpadd(t0[0], Qj[j]->Y[1], t1[1]);
            fpneg(t1[1]);
            fpadd(t1[1], *n1, t1[1]);
            fpsub(t2[1], Qj[j]->Y[0], t3[0]);
            fpadd(t2[0], Qj[j]->Y[1], t3[1]);
            fpneg(t3[1]);
            fpadd(t3[1], *n2, t3[1]);

            fp2mul_mont(t1, t3, g);
            fp2add(t4, t5, h);
            fp2_conj(h, h);
            fp2mul_mont(g, h, g);

            fp2sqr_mont(f[j+t_points], tf);
            fp2mul_mont(f[j+t_points], tf, f[j+t_points]);
            fp2mul_mont(f[j+t_points], g, f[j+t_points]);
        }
    }
    for (int j = 0; j < t_points; j++) {
        x  = (felm_t*)T_tate3 + 6*(OBOB_EXPON-1) + 0;
        y  = (felm_t*)T_tate3 + 6*(OBOB_EXPON-1) + 1;
        l1 = (felm_t*)T_tate3 + 6*(OBOB_EXPON-1) + 2;
        x2 = (felm_t*)T_tate3 + 6*(OBOB_EXPON-1) + 3;
        
        fpsub(Qj[j]->X[0], *x, t0[0]);
        fpcopy(Qj[j]->X[1], t0[1]);
        fpmul_mont(*l1, t0[0], t1[0]);
        fpmul_mont(*l1, t0[1], t1[1]);
        fp2sub(t1, Qj[j]->Y, t2);
        fpadd(t2[0], *y, t2[0]);
        fp2mul_mont(t0, t2, g);
        fpsub(Qj[j]->X[0], *x2, h[0]);
        fpcopy(Qj[j]->X[1], h[1]);
        fpneg(h[1]);
        fp2mul_mont(g, h, g);

        fp2sqr_mont(f[j], tf);
        fp2mul_mont(f[j], tf, f[j]);
        fp2mul_mont(f[j], g, f[j]);

        fpadd(Qj[j]->X[0], *x, t0[0]);
        fpmul_mont(*l1, t0[0], t1[0]);
        fpsub(Qj[j]->Y[0], t1[1], t2[0]);
        fpadd(Qj[j]->Y[1], t1[0], t2[1]);
        fpsub(t2[1], *y, t2[1]);
        fp2mul_mont(t0, t2, g);
        fpadd(Qj[j]->X[0], *x2, h[0]);
        fp2mul_mont(g, h, g);

        fp2sqr_mont(f[j+t_points], tf);
        fp2mul_mont(f[j+t_points], tf, f[j+t_points]);
        fp2mul_mont(f[j+t_points], g, f[j+t_points]);
    }

    // Final exponentiation:
    mont_n_way_inv(f, 2*t_points, finv);
    for (int j = 0; j < 2*t_points; j++) {
        final_exponentiation_3_torsion(f[j], finv[j], f[j]);
    }
}