LCOV - code coverage report
Current view: top level - ballet/bn254 - fd_bn254_field_ext.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 407 415 98.1 %
Date: 2024-11-13 11:58:15 Functions: 35 36 97.2 %

          Line data    Source code
       1             : #include "./fd_bn254.h"
       2             : 
       3             : /* Extension Fields Fp2, Fp6, Fp12.
       4             : 
       5             :    Mostly based on https://eprint.iacr.org/2010/354, Appendix A.
       6             :    See also, as a reference implementation:
       7             :    https://github.com/Consensys/gnark-crypto/tree/v0.12.1/ecc/bn254/internal/fptower
       8             : 
       9             :    Elements are in Montgomery form, unless otherwise specified. */
      10             : 
      11             : /* Constants */
      12             : 
      13             : /* const B=3/(i+9), in twist curve equation y^2 = x^3 + b'. Montgomery.
      14             :    0x2514c6324384a86d26b7edf049755260020b1b273633535d3bf938e377b802a8
      15             :    0x0141b9ce4a688d4dd749d0dd22ac00aa65f0b37d93ce0d3e38e7ecccd1dcff67 */
      16             : const fd_bn254_fp2_t fd_bn254_const_twist_b_mont[1] = {{{
      17             :   {{ 0x3bf938e377b802a8, 0x020b1b273633535d, 0x26b7edf049755260, 0x2514c6324384a86d, }},
      18             :   {{ 0x38e7ecccd1dcff67, 0x65f0b37d93ce0d3e, 0xd749d0dd22ac00aa, 0x0141b9ce4a688d4d, }},
      19             : }}};
      20             : 
      21             : /* fd_bn254_const_frob_gamma1_mont for frob. Montgomery.
      22             :    gamma_1,1 = 0x02f34d751a1f3a7c11bded5ef08a2087ca6b1d7387afb78aaf9ba69633144907
      23             :                0x10a75716b3899551dc2ff3a253dfc926d00f02a4565de15ba222ae234c492d72
      24             :    gamma_1,2 = 0x1956bcd8118214ec7a007127242e0991347f91c8a9aa6454b5773b104563ab30
      25             :                0x26694fbb4e82ebc3b6e713cdfae0ca3aaa1c7b6d89f891416e849f1ea0aa4757
      26             :    gamma_1,3 = 0x253570bea500f8dd31a9d1b6f9645366bb30f162e133bacbe4bbdd0c2936b629
      27             :                0x2c87200285defecc6d16bd27bb7edc6b07affd117826d1dba1d77ce45ffe77c7
      28             :    gamma_1,4 = 0x15df9cddbb9fd3ec9c941f314b3e2399a5bb2bd3273411fb7361d77f843abe92
      29             :                0x24830a9d3171f0fd37bc870a0c7dd2b962cb29a5a4445b605dddfd154bd8c949
      30             :    gamma_1,5 = 0x12aabced0ab0884132bee66b83c459e8e240342127694b0bc970692f41690fe7
      31             :                0x2f21ebb535d2925ad3b0a40b8a4910f505193418ab2fcc570d485d2340aebfa9 */
      32             : const fd_bn254_fp2_t fd_bn254_const_frob_gamma1_mont[5] = {
      33             :   {{
      34             :     {{ 0xaf9ba69633144907, 0xca6b1d7387afb78a, 0x11bded5ef08a2087, 0x02f34d751a1f3a7c, }},
      35             :     {{ 0xa222ae234c492d72, 0xd00f02a4565de15b, 0xdc2ff3a253dfc926, 0x10a75716b3899551, }},
      36             :   }},
      37             :   {{
      38             :     {{ 0xb5773b104563ab30, 0x347f91c8a9aa6454, 0x7a007127242e0991, 0x1956bcd8118214ec, }},
      39             :     {{ 0x6e849f1ea0aa4757, 0xaa1c7b6d89f89141, 0xb6e713cdfae0ca3a, 0x26694fbb4e82ebc3, }},
      40             :   }},
      41             :   {{
      42             :     {{ 0xe4bbdd0c2936b629, 0xbb30f162e133bacb, 0x31a9d1b6f9645366, 0x253570bea500f8dd, }},
      43             :     {{ 0xa1d77ce45ffe77c7, 0x07affd117826d1db, 0x6d16bd27bb7edc6b, 0x2c87200285defecc, }},
      44             :   }},
      45             :   {{
      46             :     {{ 0x7361d77f843abe92, 0xa5bb2bd3273411fb, 0x9c941f314b3e2399, 0x15df9cddbb9fd3ec, }},
      47             :     {{ 0x5dddfd154bd8c949, 0x62cb29a5a4445b60, 0x37bc870a0c7dd2b9, 0x24830a9d3171f0fd, }},
      48             :   }},
      49             :   {{
      50             :     {{ 0xc970692f41690fe7, 0xe240342127694b0b, 0x32bee66b83c459e8, 0x12aabced0ab08841, }},
      51             :     {{ 0x0d485d2340aebfa9, 0x05193418ab2fcc57, 0xd3b0a40b8a4910f5, 0x2f21ebb535d2925a, }},
      52             :   }},
      53             : };
      54             : 
      55             : /* fd_bn254_const_frob_gamma2_mont for frob^2. Montgomery.
      56             :    gamma_2,1 = 0x04290f65bad856e60e201271ad0d4418f0c5d61468b39769ca8d800500fa1bf2
      57             :    gamma_2,2 = 0x2682e617020217e06001b4b8b615564a7dce557cdb5e56b93350c88e13e80b9c
      58             :    gamma_2,3 = 0x2259d6b14729c0fa51e1a247090812318d087f6872aabf4f68c3488912edefaa
      59             :    gamma_2,4 = 0x2c3b3f0d26594943aa303344d4741444a6bb947cffbe332371930c11d782e155
      60             :    gamma_2,5 = 0x09e1685bdf2f8849584e90fdcb6c021319b315148d1373d408cfc388c494f1ab */
      61             : const fd_bn254_fp_t fd_bn254_const_frob_gamma2_mont[5] = {
      62             :   {{ 0xca8d800500fa1bf2, 0xf0c5d61468b39769, 0x0e201271ad0d4418, 0x04290f65bad856e6, }}, /* gamma_2,1 */
      63             :   {{ 0x3350c88e13e80b9c, 0x7dce557cdb5e56b9, 0x6001b4b8b615564a, 0x2682e617020217e0, }}, /* gamma_2,2 */
      64             :   {{ 0x68c3488912edefaa, 0x8d087f6872aabf4f, 0x51e1a24709081231, 0x2259d6b14729c0fa, }}, /* gamma_2,3 */
      65             :   {{ 0x71930c11d782e155, 0xa6bb947cffbe3323, 0xaa303344d4741444, 0x2c3b3f0d26594943, }}, /* gamma_2,4 */
      66             :   {{ 0x08cfc388c494f1ab, 0x19b315148d1373d4, 0x584e90fdcb6c0213, 0x09e1685bdf2f8849, }}, /* gamma_2,5 */
      67             : };
      68             : 
      69             : /* Fp2 */
      70             : 
      71             : static inline fd_bn254_fp2_t *
      72             : fd_bn254_fp2_frombytes_be_nm( fd_bn254_fp2_t * r,
      73             :                               uchar const      buf[64],
      74             :                               int *            is_inf,
      75        3528 :                               int *            is_neg ) {
      76             :   /* validate fp2.el[0] without flags */
      77        3528 :   if( FD_UNLIKELY( !fd_bn254_fp_frombytes_be_nm( &r->el[0], &buf[32], NULL, NULL ) ) ) {
      78        1056 :     return NULL;
      79        1056 :   }
      80             :   /* validate fp2.el[1] with flags */
      81        2472 :   if( FD_UNLIKELY( !fd_bn254_fp_frombytes_be_nm( &r->el[1], &buf[0], is_inf, is_neg ) ) ) {
      82         636 :     return NULL;
      83         636 :   }
      84        1836 :   return r;
      85        2472 : }
      86             : 
      87             : static inline uchar *
      88             : fd_bn254_fp2_tobytes_be_nm( uchar                  buf[64],
      89         270 :                             fd_bn254_fp2_t * const a ) {
      90         270 :   fd_bn254_fp_tobytes_be_nm( &buf[ 0], &a->el[1] );
      91         270 :   fd_bn254_fp_tobytes_be_nm( &buf[32], &a->el[0] );
      92         270 :   return buf;
      93         270 : }
      94             : 
      95             : /* fd_bn254_fp2_is_neg_nm checks wheather x < 0 in Fp2.
      96             :    Note: x is NON Montgomery.
      97             :    Returns 1 if x < 0, 0 otherwise. */
      98             : static inline int
      99         345 : fd_bn254_fp2_is_neg_nm( fd_bn254_fp2_t * x ) {
     100         345 :   if( FD_UNLIKELY( fd_bn254_fp_is_zero( &x->el[1] ) ) ) {
     101          69 :     return fd_bn254_fp_is_neg_nm( &x->el[0] );
     102          69 :   }
     103         276 :   return fd_bn254_fp_is_neg_nm( &x->el[1] );
     104         345 : }
     105             : 
     106             : /* fd_bn254_fp2_is_minus_one checks wheather a == -1 in Fp2.
     107             :    Returns 1 if a==-1, 0 otherwise. */
     108             : static inline int
     109         576 : fd_bn254_fp2_is_minus_one( fd_bn254_fp2_t const * a ) {
     110         576 :   return fd_uint256_eq( &a->el[0], fd_bn254_const_p_minus_one_mont )
     111         576 :       && fd_uint256_eq( &a->el[1], fd_bn254_const_zero );
     112         576 : }
     113             : 
     114             : /* fd_bn254_fp2_eq checks wheather a == b in Fp2.
     115             :    Returns 1 if a == b, 0 otherwise. */
     116             : static inline int
     117             : fd_bn254_fp2_eq( fd_bn254_fp2_t const * a,
     118       10602 :                  fd_bn254_fp2_t const * b ) {
     119       10602 :   return fd_bn254_fp_eq( &a->el[0], &b->el[0] )
     120       10602 :       && fd_bn254_fp_eq( &a->el[1], &b->el[1] );
     121       10602 : }
     122             : 
     123             : /* fd_bn254_fp2_set sets r = a. */
     124             : static inline fd_bn254_fp2_t *
     125             : fd_bn254_fp2_set( fd_bn254_fp2_t * r,
     126      601740 :                   fd_bn254_fp2_t const * a ) {
     127      601740 :   fd_bn254_fp_set( &r->el[0], &a->el[0] );
     128      601740 :   fd_bn254_fp_set( &r->el[1], &a->el[1] );
     129      601740 :   return r;
     130      601740 : }
     131             : 
     132             : /* fd_bn254_fp2_from_mont sets r = a, coverting into Mongomery form. */
     133             : static inline fd_bn254_fp2_t *
     134             : fd_bn254_fp2_from_mont( fd_bn254_fp2_t * r,
     135         270 :                         fd_bn254_fp2_t const * a ) {
     136         270 :   fd_bn254_fp_from_mont( &r->el[0], &a->el[0] );
     137         270 :   fd_bn254_fp_from_mont( &r->el[1], &a->el[1] );
     138         270 :   return r;
     139         270 : }
     140             : 
     141             : /* fd_bn254_fp2_to_mont sets r = a, coverting into NON Mongomery form. */
     142             : static inline fd_bn254_fp2_t *
     143             : fd_bn254_fp2_to_mont( fd_bn254_fp2_t * r,
     144        1038 :                       fd_bn254_fp2_t const * a ) {
     145        1038 :   fd_bn254_fp_to_mont( &r->el[0], &a->el[0] );
     146        1038 :   fd_bn254_fp_to_mont( &r->el[1], &a->el[1] );
     147        1038 :   return r;
     148        1038 : }
     149             : 
     150             : /* fd_bn254_fp2_neg_nm sets r = -x in Fp2.
     151             :    Note: x is NON Montgomery. */
     152             : static inline fd_bn254_fp2_t *
     153             : fd_bn254_fp2_neg_nm( fd_bn254_fp2_t * r,
     154          36 :                      fd_bn254_fp2_t const * x ) {
     155          36 :   fd_bn254_fp_neg_nm( &r->el[0], &x->el[0] );
     156          36 :   fd_bn254_fp_neg_nm( &r->el[1], &x->el[1] );
     157          36 :   return r;
     158          36 : }
     159             : 
     160             : /* fd_bn254_fp2_neg sets r = -a in Fp2. */
     161             : static inline fd_bn254_fp2_t *
     162             : fd_bn254_fp2_neg( fd_bn254_fp2_t * r,
     163       30456 :                   fd_bn254_fp2_t const * a ) {
     164       30456 :   fd_bn254_fp_neg( &r->el[0], &a->el[0] );
     165       30456 :   fd_bn254_fp_neg( &r->el[1], &a->el[1] );
     166       30456 :   return r;
     167       30456 : }
     168             : 
     169             : /* fd_bn254_fp2_neg sets r = a/2 in Fp2. */
     170             : static inline fd_bn254_fp2_t *
     171             : fd_bn254_fp2_halve( fd_bn254_fp2_t * r,
     172       32256 :                     fd_bn254_fp2_t const * a ) {
     173       32256 :   fd_bn254_fp_halve( &r->el[0], &a->el[0] );
     174       32256 :   fd_bn254_fp_halve( &r->el[1], &a->el[1] );
     175       32256 :   return r;
     176       32256 : }
     177             : 
     178             : /* fd_bn254_fp2_add computes r = a + b in Fp2. */
     179             : static inline fd_bn254_fp2_t *
     180             : fd_bn254_fp2_add( fd_bn254_fp2_t * r,
     181             :                   fd_bn254_fp2_t const * a,
     182     3087558 :                   fd_bn254_fp2_t const * b ) {
     183     3087558 :   fd_bn254_fp_add( &r->el[0], &a->el[0], &b->el[0] );
     184     3087558 :   fd_bn254_fp_add( &r->el[1], &a->el[1], &b->el[1] );
     185     3087558 :   return r;
     186     3087558 : }
     187             : 
     188             : /* fd_bn254_fp2_sub computes r = a - b in Fp2. */
     189             : static inline fd_bn254_fp2_t *
     190             : fd_bn254_fp2_sub( fd_bn254_fp2_t * r,
     191             :                   fd_bn254_fp2_t const * a,
     192     1955916 :                   fd_bn254_fp2_t const * b ) {
     193     1955916 :   fd_bn254_fp_sub( &r->el[0], &a->el[0], &b->el[0] );
     194     1955916 :   fd_bn254_fp_sub( &r->el[1], &a->el[1], &b->el[1] );
     195     1955916 :   return r;
     196     1955916 : }
     197             : 
     198             : /* fd_bn254_fp2_conj computes r = conj(a) in Fp2.
     199             :    If a = a0 + a1*i, conj(a) = a0 - a1*i. */
     200             : static inline fd_bn254_fp2_t *
     201             : fd_bn254_fp2_conj( fd_bn254_fp2_t * r,
     202        6282 :                    fd_bn254_fp2_t const * a ) {
     203        6282 :   fd_bn254_fp_set( &r->el[0], &a->el[0] );
     204        6282 :   fd_bn254_fp_neg( &r->el[1], &a->el[1] );
     205        6282 :   return r;
     206        6282 : }
     207             : 
     208             : /* fd_bn254_fp2_mul computes r = a * b in Fp2.
     209             :    Karatsuba mul + reduction given that i^2 = -1.
     210             :    Note: this can probably be optimized, see for ideas:
     211             :    https://eprint.iacr.org/2010/354 */
     212             : static inline fd_bn254_fp2_t *
     213             : fd_bn254_fp2_mul( fd_bn254_fp2_t * r,
     214             :                   fd_bn254_fp2_t const * a,
     215     1122720 :                   fd_bn254_fp2_t const * b ) {
     216     1122720 :   fd_bn254_fp_t const * a0 = &a->el[0];
     217     1122720 :   fd_bn254_fp_t const * a1 = &a->el[1];
     218     1122720 :   fd_bn254_fp_t const * b0 = &b->el[0];
     219     1122720 :   fd_bn254_fp_t const * b1 = &b->el[1];
     220     1122720 :   fd_bn254_fp_t * r0 = &r->el[0];
     221     1122720 :   fd_bn254_fp_t * r1 = &r->el[1];
     222     1122720 :   fd_bn254_fp_t a0b0[1], a1b1[1], sa[1], sb[1];
     223             : 
     224     1122720 :   fd_bn254_fp_add( sa, a0, a1 );
     225     1122720 :   fd_bn254_fp_add( sb, b0, b1 );
     226             : 
     227     1122720 :   fd_bn254_fp_mul( a0b0, a0, b0 );
     228     1122720 :   fd_bn254_fp_mul( a1b1, a1, b1 );
     229     1122720 :   fd_bn254_fp_mul( r1, sa, sb );
     230             : 
     231     1122720 :   fd_bn254_fp_sub( r0, a0b0, a1b1 ); /* i^2 = -1 */
     232     1122720 :   fd_bn254_fp_sub( r1, r1, a0b0 );
     233     1122720 :   fd_bn254_fp_sub( r1, r1, a1b1 );
     234     1122720 :   return r;
     235     1122720 : }
     236             : 
     237             : /* fd_bn254_fp2_mul computes r = a^2 in Fp2.
     238             :    https://eprint.iacr.org/2010/354, Alg. 3.
     239             :    This is done with 2mul in Fp, instead of 2sqr+1mul. */
     240             : static inline fd_bn254_fp2_t *
     241             : fd_bn254_fp2_sqr( fd_bn254_fp2_t * r,
     242      899292 :                   fd_bn254_fp2_t const * a ) {
     243      899292 :   fd_bn254_fp_t p[1], m[1];
     244      899292 :   fd_bn254_fp_add( p, &a->el[0], &a->el[1] );
     245      899292 :   fd_bn254_fp_sub( m, &a->el[0], &a->el[1] );
     246             :   /* r1 = 2 a0*a1 */
     247      899292 :   fd_bn254_fp_mul( &r->el[1], &a->el[0], &a->el[1] );
     248      899292 :   fd_bn254_fp_add( &r->el[1], &r->el[1], &r->el[1] );
     249             :   /* r0 = (a0-a1)*(a0+a1) */
     250      899292 :   fd_bn254_fp_mul( &r->el[0], p, m );
     251      899292 :   return r;
     252      899292 : }
     253             : 
     254             : /* fd_bn254_fp2_mul_by_i computes r = a * i in Fp2. */
     255             : static inline fd_bn254_fp2_t *
     256             : fd_bn254_fp2_mul_by_i( fd_bn254_fp2_t * r,
     257           0 :                        fd_bn254_fp2_t const * a ) {
     258           0 :   fd_bn254_fp_t t[1];
     259           0 :   fd_bn254_fp_neg( t, &a->el[1] );
     260           0 :   fd_bn254_fp_set( &r->el[1], &a->el[0] );
     261           0 :   fd_bn254_fp_set( &r->el[0], t );
     262           0 :   return r;
     263           0 : }
     264             : 
     265             : /* fd_bn254_fp2_inv computes r = 1 / a in Fp2.
     266             :    https://eprint.iacr.org/2010/354, Alg. 8. */
     267             : static inline fd_bn254_fp2_t *
     268             : fd_bn254_fp2_inv( fd_bn254_fp2_t * r,
     269         264 :                   FD_PARAM_UNUSED fd_bn254_fp2_t const * a ) {
     270         264 :   fd_bn254_fp_t t0[1], t1[1];
     271         264 :   fd_bn254_fp_sqr( t0, &a->el[0] );
     272         264 :   fd_bn254_fp_sqr( t1, &a->el[1] );
     273         264 :   fd_bn254_fp_add( t0, t0, t1 );
     274         264 :   fd_bn254_fp_inv( t1, t0 );
     275         264 :   fd_bn254_fp_mul( &r->el[0], &a->el[0], t1 );
     276         264 :   fd_bn254_fp_mul( &r->el[1], &a->el[1], t1 );
     277         264 :   fd_bn254_fp_neg( &r->el[1], &r->el[1] );
     278         264 :   return r;
     279         264 : }
     280             : 
     281             : /* fd_bn254_fp2_pow computes r = a ^ b in Fp2. */
     282             : fd_bn254_fp2_t *
     283             : fd_bn254_fp2_pow( fd_bn254_fp2_t * restrict r,
     284             :                   fd_bn254_fp2_t const *    a,
     285         576 :                   fd_uint256_t const *      b ) {
     286         576 :   fd_bn254_fp2_set_one( r );
     287             : 
     288         576 :   int i = 255;
     289        2610 :   while( !fd_uint256_bit( b, i) ) i--;
     290      145998 :   for( ; i>=0; i--) {
     291      145422 :     fd_bn254_fp2_sqr( r, r );
     292      145422 :     if( fd_uint256_bit( b, i ) ) {
     293       63054 :       fd_bn254_fp2_mul( r, r, a );
     294       63054 :     }
     295      145422 :   }
     296         576 :   return r;
     297         576 : }
     298             : 
     299             : /* fd_bn254_fp2_sqrt computes r = sqrt(a) in Fp2.
     300             :    https://eprint.iacr.org/2012/685, Alg. 9.
     301             :    Note: r is one of the two sqrt, the other is -r. This function
     302             :    can return either the positive or negative one, no assumptions/promises.
     303             :    Returns r if a is a square (sqrt exists), or NULL otherwise. */
     304             : static inline fd_bn254_fp2_t *
     305             : fd_bn254_fp2_sqrt( fd_bn254_fp2_t * r,
     306         306 :                    fd_bn254_fp2_t const * a ) {
     307         306 :   fd_bn254_fp2_t a0[1], a1[1], alpha[1], x0[1];
     308             : 
     309         306 :   fd_bn254_fp2_pow( a1, a, fd_bn254_const_sqrt_exp );
     310             : 
     311         306 :   fd_bn254_fp2_sqr( alpha, a1 );
     312         306 :   fd_bn254_fp2_mul( alpha, alpha, a );
     313             : 
     314         306 :   fd_bn254_fp2_conj( a0, alpha );
     315         306 :   fd_bn254_fp2_mul( a0, a0, alpha );
     316             : 
     317         306 :   if( FD_UNLIKELY( fd_bn254_fp2_is_minus_one( a0 ) ) ) {
     318          36 :     return NULL;
     319          36 :   }
     320             : 
     321         270 :   fd_bn254_fp2_mul( x0, a1, a );
     322         270 :   if( fd_bn254_fp2_is_minus_one( alpha ) ) {
     323             :     /* COV: I don't know if there's a point that hits this condition.
     324             :        sqrt(-1) hits this, but doesn't correspond to a valid point.
     325             :        Tried with some other possible values, nothing corresponds to a point. */
     326           0 :     fd_bn254_fp2_mul_by_i( r, x0 );
     327         270 :   } else {
     328         270 :     fd_bn254_fp2_set_one( a1 );
     329         270 :     fd_bn254_fp2_add( a0, alpha, a1 );                           /* 1 + alpha */
     330         270 :     fd_bn254_fp2_pow( a1, a0, fd_bn254_const_p_minus_one_half ); /* b */
     331         270 :     fd_bn254_fp2_mul( r, a1, x0 );
     332         270 :   }
     333         270 :   return r;
     334         306 : }
     335             : 
     336             : /* fd_bn254_fp2_mul_by_xi computes r = a * (9+i) in Fp2.
     337             :    xi = (9+i) is the const used to build Fp6.
     338             :    Note: this can probably be optimized (less reductions mod p). */
     339             : static inline fd_bn254_fp2_t *
     340             : fd_bn254_fp2_mul_by_xi( fd_bn254_fp2_t * r,
     341      535668 :                         fd_bn254_fp2_t const * a ) {
     342             :   /* xi = 9 + i
     343             :      r = (9*a0 - a1) + (9*a1 + a0) i */
     344      535668 :   fd_bn254_fp_t r0[1], r1[1];
     345             : 
     346      535668 :   fd_bn254_fp_add( r0, &a->el[0], &a->el[0] );
     347      535668 :   fd_bn254_fp_add( r0, r0, r0 );
     348      535668 :   fd_bn254_fp_add( r0, r0, r0 );
     349      535668 :   fd_bn254_fp_add( r0, r0, &a->el[0] );
     350      535668 :   fd_bn254_fp_sub( r0, r0, &a->el[1] );
     351             : 
     352      535668 :   fd_bn254_fp_add( r1, &a->el[1], &a->el[1] );
     353      535668 :   fd_bn254_fp_add( r1, r1, r1 );
     354      535668 :   fd_bn254_fp_add( r1, r1, r1 );
     355      535668 :   fd_bn254_fp_add( r1, r1, &a->el[1] );
     356      535668 :   fd_bn254_fp_add( &r->el[1], r1, &a->el[0] );
     357             : 
     358      535668 :   fd_bn254_fp_set( &r->el[0], r0 );
     359      535668 :   return r;
     360      535668 : }
     361             : 
     362             : /* Fp6 */
     363             : 
     364             : static inline fd_bn254_fp6_t *
     365             : fd_bn254_fp6_set( fd_bn254_fp6_t * r,
     366        1320 :                   fd_bn254_fp6_t const * a ) {
     367        1320 :   fd_bn254_fp2_set( &r->el[0], &a->el[0] );
     368        1320 :   fd_bn254_fp2_set( &r->el[1], &a->el[1] );
     369        1320 :   fd_bn254_fp2_set( &r->el[2], &a->el[2] );
     370        1320 :   return r;
     371        1320 : }
     372             : 
     373             : static inline fd_bn254_fp6_t *
     374             : fd_bn254_fp6_neg( fd_bn254_fp6_t * r,
     375        1584 :                      fd_bn254_fp6_t const * a ) {
     376        1584 :   fd_bn254_fp2_neg( &r->el[0], &a->el[0] );
     377        1584 :   fd_bn254_fp2_neg( &r->el[1], &a->el[1] );
     378        1584 :   fd_bn254_fp2_neg( &r->el[2], &a->el[2] );
     379        1584 :   return r;
     380        1584 : }
     381             : 
     382             : static inline fd_bn254_fp6_t *
     383             : fd_bn254_fp6_add( fd_bn254_fp6_t * r,
     384             :                   fd_bn254_fp6_t const * a,
     385      146844 :                   fd_bn254_fp6_t const * b ) {
     386      146844 :   fd_bn254_fp2_add( &r->el[0], &a->el[0], &b->el[0] );
     387      146844 :   fd_bn254_fp2_add( &r->el[1], &a->el[1], &b->el[1] );
     388      146844 :   fd_bn254_fp2_add( &r->el[2], &a->el[2], &b->el[2] );
     389      146844 :   return r;
     390      146844 : }
     391             : 
     392             : static inline fd_bn254_fp6_t *
     393             : fd_bn254_fp6_sub( fd_bn254_fp6_t * r,
     394             :                   fd_bn254_fp6_t const * a,
     395       98160 :                   fd_bn254_fp6_t const * b ) {
     396       98160 :   fd_bn254_fp2_sub( &r->el[0], &a->el[0], &b->el[0] );
     397       98160 :   fd_bn254_fp2_sub( &r->el[1], &a->el[1], &b->el[1] );
     398       98160 :   fd_bn254_fp2_sub( &r->el[2], &a->el[2], &b->el[2] );
     399       98160 :   return r;
     400       98160 : }
     401             : 
     402             : static inline fd_bn254_fp6_t *
     403             : fd_bn254_fp6_mul_by_gamma( fd_bn254_fp6_t * r,
     404       59196 :                            fd_bn254_fp6_t const * a ) {
     405             :   /* https://eprint.iacr.org/2010/354, Alg. 12 */
     406       59196 :   fd_bn254_fp2_t t[1];
     407       59196 :   fd_bn254_fp2_mul_by_xi( t, &a->el[2] );
     408       59196 :   fd_bn254_fp2_set( &r->el[2], &a->el[1] );
     409       59196 :   fd_bn254_fp2_set( &r->el[1], &a->el[0] );
     410       59196 :   fd_bn254_fp2_set( &r->el[0], t );
     411       59196 :   return r;
     412       59196 : }
     413             : 
     414             : static inline fd_bn254_fp6_t *
     415             : fd_bn254_fp6_mul( fd_bn254_fp6_t * r,
     416             :                   fd_bn254_fp6_t const * a,
     417      137388 :                   fd_bn254_fp6_t const * b ) {
     418             :   /* https://eprint.iacr.org/2010/354, Alg. 13 */
     419      137388 :   fd_bn254_fp2_t const * a0 = &a->el[0];
     420      137388 :   fd_bn254_fp2_t const * a1 = &a->el[1];
     421      137388 :   fd_bn254_fp2_t const * a2 = &a->el[2];
     422      137388 :   fd_bn254_fp2_t const * b0 = &b->el[0];
     423      137388 :   fd_bn254_fp2_t const * b1 = &b->el[1];
     424      137388 :   fd_bn254_fp2_t const * b2 = &b->el[2];
     425      137388 :   fd_bn254_fp2_t a0b0[1], a1b1[1], a2b2[1];
     426      137388 :   fd_bn254_fp2_t sa[1], sb[1];
     427      137388 :   fd_bn254_fp2_t r0[1], r1[1], r2[1];
     428             : 
     429      137388 :   fd_bn254_fp2_mul( a0b0, a0, b0 );
     430      137388 :   fd_bn254_fp2_mul( a1b1, a1, b1 );
     431      137388 :   fd_bn254_fp2_mul( a2b2, a2, b2 );
     432             : 
     433      137388 :   fd_bn254_fp2_add( sa, a1, a2 );
     434      137388 :   fd_bn254_fp2_add( sb, b1, b2 );
     435      137388 :   fd_bn254_fp2_mul( r0, sa, sb );
     436      137388 :   fd_bn254_fp2_sub( r0, r0, a1b1 );
     437      137388 :   fd_bn254_fp2_sub( r0, r0, a2b2 );
     438      137388 :   fd_bn254_fp2_mul_by_xi( r0, r0 );
     439      137388 :   fd_bn254_fp2_add( r0, r0, a0b0 );
     440             : 
     441      137388 :   fd_bn254_fp2_add( sa, a0, a2 );
     442      137388 :   fd_bn254_fp2_add( sb, b0, b2 );
     443      137388 :   fd_bn254_fp2_mul( r2, sa, sb );
     444      137388 :   fd_bn254_fp2_sub( r2, r2, a0b0 );
     445      137388 :   fd_bn254_fp2_sub( r2, r2, a2b2 );
     446      137388 :   fd_bn254_fp2_add( r2, r2, a1b1 );
     447             : 
     448      137388 :   fd_bn254_fp2_add( sa, a0, a1 );
     449      137388 :   fd_bn254_fp2_add( sb, b0, b1 );
     450      137388 :   fd_bn254_fp2_mul( r1, sa, sb );
     451      137388 :   fd_bn254_fp2_sub( r1, r1, a0b0 );
     452      137388 :   fd_bn254_fp2_sub( r1, r1, a1b1 );
     453      137388 :   fd_bn254_fp2_mul_by_xi( a2b2, a2b2 );
     454      137388 :   fd_bn254_fp2_add( r1, r1, a2b2 );
     455             : 
     456      137388 :   fd_bn254_fp2_set( &r->el[0], r0 );
     457      137388 :   fd_bn254_fp2_set( &r->el[1], r1 );
     458      137388 :   fd_bn254_fp2_set( &r->el[2], r2 );
     459      137388 :   return r;
     460      137388 : }
     461             : 
     462             : static inline fd_bn254_fp6_t *
     463             : fd_bn254_fp6_sqr( fd_bn254_fp6_t * r,
     464         528 :                   fd_bn254_fp6_t const * a ) {
     465             :   /* https://eprint.iacr.org/2010/354, Alg. 16 */
     466         528 :   fd_bn254_fp2_t const * a0 = &a->el[0];
     467         528 :   fd_bn254_fp2_t const * a1 = &a->el[1];
     468         528 :   fd_bn254_fp2_t const * a2 = &a->el[2];
     469         528 :   fd_bn254_fp2_t c0[1], c1[1], c2[1];
     470         528 :   fd_bn254_fp2_t c3[1], c4[1], c5[1];
     471             : 
     472         528 :   fd_bn254_fp2_mul( c4, a0, a1 );
     473         528 :   fd_bn254_fp2_add( c4, c4, c4 );
     474         528 :   fd_bn254_fp2_sqr( c5, a2 );
     475             : 
     476         528 :   fd_bn254_fp2_sub( c2, c4, c5 );
     477         528 :   fd_bn254_fp2_mul_by_xi( c5, c5 );
     478         528 :   fd_bn254_fp2_add( c1, c4, c5 );
     479             : 
     480         528 :   fd_bn254_fp2_sqr( c3, a0 );
     481         528 :   fd_bn254_fp2_sub( c4, a0, a1 );
     482         528 :   fd_bn254_fp2_add( c4, c4, a2 );
     483             : 
     484         528 :   fd_bn254_fp2_mul( c5, a1, a2 );
     485         528 :   fd_bn254_fp2_add( c5, c5, c5 );
     486         528 :   fd_bn254_fp2_sqr( c4, c4 );
     487             : 
     488         528 :   fd_bn254_fp2_add( c2, c2, c4 );
     489         528 :   fd_bn254_fp2_add( c2, c2, c5 );
     490         528 :   fd_bn254_fp2_sub( c2, c2, c3 );
     491         528 :   fd_bn254_fp2_mul_by_xi( c5, c5 );
     492         528 :   fd_bn254_fp2_add( c0, c3, c5 );
     493             : 
     494         528 :   fd_bn254_fp2_set( &r->el[0], c0 );
     495         528 :   fd_bn254_fp2_set( &r->el[1], c1 );
     496         528 :   fd_bn254_fp2_set( &r->el[2], c2 );
     497         528 :   return r;
     498         528 : }
     499             : 
     500             : static inline fd_bn254_fp6_t *
     501             : fd_bn254_fp6_inv( fd_bn254_fp6_t * r,
     502         264 :                   fd_bn254_fp6_t const * a ) {
     503             :   /* https://eprint.iacr.org/2010/354, Alg. 17 */
     504         264 :   fd_bn254_fp2_t t[6];
     505         264 :   fd_bn254_fp2_sqr( &t[0], &a->el[0] );
     506         264 :   fd_bn254_fp2_sqr( &t[1], &a->el[1] );
     507         264 :   fd_bn254_fp2_sqr( &t[2], &a->el[2] );
     508         264 :   fd_bn254_fp2_mul( &t[3], &a->el[0], &a->el[1] );
     509         264 :   fd_bn254_fp2_mul( &t[4], &a->el[0], &a->el[2] );
     510         264 :   fd_bn254_fp2_mul( &t[5], &a->el[1], &a->el[2] );
     511             :   /* t0 := c0 = t0 - xi * t5 */
     512         264 :   fd_bn254_fp2_mul_by_xi( &t[5], &t[5] );
     513         264 :   fd_bn254_fp2_sub( &t[0], &t[0], &t[5] );
     514             :   /* t2 := c1 = xi * t2 - t3 */
     515         264 :   fd_bn254_fp2_mul_by_xi( &t[2], &t[2] );
     516         264 :   fd_bn254_fp2_sub( &t[2], &t[2], &t[3] );
     517             :   /* t1 := c2 = t1 - t4 (note: paper says t1*t4, but that's a misprint) */
     518         264 :   fd_bn254_fp2_sub( &t[1], &t[1], &t[4] );
     519             :   /* t3 := t6 = a0 * c0 */
     520         264 :   fd_bn254_fp2_mul( &t[3], &a->el[0], &t[0] );
     521             :   /* t3 := t6 = t6 + (xi * a2 * c1 =: t4) */
     522         264 :   fd_bn254_fp2_mul( &t[4], &a->el[2], &t[2] );
     523         264 :   fd_bn254_fp2_mul_by_xi( &t[4], &t[4] );
     524         264 :   fd_bn254_fp2_add( &t[3], &t[3], &t[4] );
     525             :   /* t3 := t6 = t6 + (xi * a2 * c1 =: t4) */
     526         264 :   fd_bn254_fp2_mul( &t[5], &a->el[1], &t[1] );
     527         264 :   fd_bn254_fp2_mul_by_xi( &t[5], &t[5] );
     528         264 :   fd_bn254_fp2_add( &t[3], &t[3], &t[5] );
     529             :   /* t4 := t6^-1 */
     530         264 :   fd_bn254_fp2_inv( &t[4], &t[3] );
     531             : 
     532         264 :   fd_bn254_fp2_mul( &r->el[0], &t[0], &t[4] );
     533         264 :   fd_bn254_fp2_mul( &r->el[1], &t[2], &t[4] );
     534         264 :   fd_bn254_fp2_mul( &r->el[2], &t[1], &t[4] );
     535         264 :   return r;
     536         264 : }
     537             : 
     538             : /* Fp12 */
     539             : 
     540             : static inline fd_bn254_fp12_t *
     541             : fd_bn254_fp12_conj( fd_bn254_fp12_t * r,
     542        1320 :                     fd_bn254_fp12_t const * a ) {
     543        1320 :   fd_bn254_fp6_set( &r->el[0], &a->el[0] );
     544        1320 :   fd_bn254_fp6_neg( &r->el[1], &a->el[1] );
     545        1320 :   return r;
     546        1320 : }
     547             : 
     548             : /*
     549             : static inline fd_bn254_fp12_t *
     550             : fd_bn254_fp12_add( fd_bn254_fp12_t * r,
     551             :                    fd_bn254_fp12_t const * a,
     552             :                    fd_bn254_fp12_t const * b ) {
     553             :   fd_bn254_fp6_add( &r->el[0], &a->el[0], &b->el[0] );
     554             :   fd_bn254_fp6_add( &r->el[1], &a->el[1], &b->el[1] );
     555             :   return r;
     556             : }
     557             : 
     558             : static inline fd_bn254_fp12_t *
     559             : fd_bn254_fp12_sub( fd_bn254_fp12_t * r,
     560             :                    fd_bn254_fp12_t const * a,
     561             :                    fd_bn254_fp12_t const * b ) {
     562             :   fd_bn254_fp6_sub( &r->el[0], &a->el[0], &b->el[0] );
     563             :   fd_bn254_fp6_sub( &r->el[1], &a->el[1], &b->el[1] );
     564             :   return r;
     565             : }
     566             : */
     567             : 
     568             : fd_bn254_fp12_t *
     569             : fd_bn254_fp12_mul( fd_bn254_fp12_t * r,
     570             :                    fd_bn254_fp12_t const * a,
     571       38964 :                    fd_bn254_fp12_t const * b ) {
     572             :   /* https://eprint.iacr.org/2010/354, Alg. 20 */
     573       38964 :   fd_bn254_fp6_t const * a0 = &a->el[0];
     574       38964 :   fd_bn254_fp6_t const * a1 = &a->el[1];
     575       38964 :   fd_bn254_fp6_t const * b0 = &b->el[0];
     576       38964 :   fd_bn254_fp6_t const * b1 = &b->el[1];
     577       38964 :   fd_bn254_fp6_t * r0 = &r->el[0];
     578       38964 :   fd_bn254_fp6_t * r1 = &r->el[1];
     579       38964 :   fd_bn254_fp6_t a0b0[1], a1b1[1], sa[1], sb[1];
     580             : 
     581       38964 :   fd_bn254_fp6_add( sa, a0, a1 );
     582       38964 :   fd_bn254_fp6_add( sb, b0, b1 );
     583             : 
     584       38964 :   fd_bn254_fp6_mul( a0b0, a0, b0 );
     585       38964 :   fd_bn254_fp6_mul( a1b1, a1, b1 );
     586       38964 :   fd_bn254_fp6_mul( r1, sa, sb );
     587             : 
     588       38964 :   fd_bn254_fp6_sub( r1, r1, a0b0 );
     589       38964 :   fd_bn254_fp6_sub( r1, r1, a1b1 );
     590             : 
     591       38964 :   fd_bn254_fp6_mul_by_gamma( a1b1, a1b1 );
     592       38964 :   fd_bn254_fp6_add( r0, a0b0, a1b1 );
     593       38964 :   return r;
     594       38964 : }
     595             : 
     596             : static inline fd_bn254_fp12_t *
     597             : fd_bn254_fp12_sqr( fd_bn254_fp12_t * r,
     598        9984 :                         fd_bn254_fp12_t const * a ) {
     599             :   /* https://eprint.iacr.org/2010/354, Alg. 22. */
     600        9984 :   fd_bn254_fp6_t c0[1], c2[1], c3[1];
     601        9984 :   fd_bn254_fp6_sub( c0, &a->el[0], &a->el[1] );
     602        9984 :   fd_bn254_fp6_mul_by_gamma( c3, &a->el[1] );
     603        9984 :   fd_bn254_fp6_sub( c3, &a->el[0], c3 );
     604        9984 :   fd_bn254_fp6_mul( c2, &a->el[0], &a->el[1] );
     605        9984 :   fd_bn254_fp6_mul( c0, c0, c3 );
     606        9984 :   fd_bn254_fp6_add( c0, c0, c2 );
     607        9984 :   fd_bn254_fp6_add( &r->el[1], c2, c2 );
     608        9984 :   fd_bn254_fp6_mul_by_gamma( &r->el[0], c2 );
     609        9984 :   fd_bn254_fp6_add( &r->el[0], &r->el[0], c0 );
     610        9984 :   return r;
     611        9984 : }
     612             : 
     613             : static inline fd_bn254_fp12_t *
     614             : fd_bn254_fp12_sqr_fast( fd_bn254_fp12_t * r,
     615       49896 :                         fd_bn254_fp12_t const * a ) {
     616             :   /* Cyclotomic sqr, https://eprint.iacr.org/2009/565, Sec. 3.2.
     617             :      Variant of https://eprint.iacr.org/2010/354, Alg. 24.
     618             :      This works when a^(p^6+1)=1, e.g. during pairing final exp. */
     619       49896 :   fd_bn254_fp2_t t[9];
     620             : 
     621       49896 :   fd_bn254_fp2_sqr( &t[0], &a->el[1].el[1] );
     622       49896 :   fd_bn254_fp2_sqr( &t[1], &a->el[0].el[0] );
     623       49896 :   fd_bn254_fp2_add( &t[6], &a->el[1].el[1], &a->el[0].el[0] );
     624       49896 :   fd_bn254_fp2_sqr( &t[6], &t[6] );
     625       49896 :   fd_bn254_fp2_sub( &t[6], &t[6], &t[0] );
     626       49896 :   fd_bn254_fp2_sub( &t[6], &t[6], &t[1] );
     627             : 
     628       49896 :   fd_bn254_fp2_sqr( &t[2], &a->el[0].el[2] );
     629       49896 :   fd_bn254_fp2_sqr( &t[3], &a->el[1].el[0] );
     630       49896 :   fd_bn254_fp2_add( &t[7], &a->el[0].el[2], &a->el[1].el[0] );
     631       49896 :   fd_bn254_fp2_sqr( &t[7], &t[7] );
     632       49896 :   fd_bn254_fp2_sub( &t[7], &t[7], &t[2] );
     633       49896 :   fd_bn254_fp2_sub( &t[7], &t[7], &t[3] );
     634             : 
     635       49896 :   fd_bn254_fp2_sqr( &t[4], &a->el[1].el[2] );
     636       49896 :   fd_bn254_fp2_sqr( &t[5], &a->el[0].el[1] );
     637       49896 :   fd_bn254_fp2_add( &t[8], &a->el[1].el[2], &a->el[0].el[1] );
     638       49896 :   fd_bn254_fp2_sqr( &t[8], &t[8] );
     639       49896 :   fd_bn254_fp2_sub( &t[8], &t[8], &t[4] );
     640       49896 :   fd_bn254_fp2_sub( &t[8], &t[8], &t[5] );
     641       49896 :   fd_bn254_fp2_mul_by_xi( &t[8], &t[8] );
     642             : 
     643       49896 :   fd_bn254_fp2_mul_by_xi( &t[0], &t[0] );
     644       49896 :   fd_bn254_fp2_add( &t[0], &t[0], &t[1] );
     645       49896 :   fd_bn254_fp2_mul_by_xi( &t[2], &t[2] );
     646       49896 :   fd_bn254_fp2_add( &t[2], &t[2], &t[3] );
     647       49896 :   fd_bn254_fp2_mul_by_xi( &t[4], &t[4] );
     648       49896 :   fd_bn254_fp2_add( &t[4], &t[4], &t[5] );
     649             : 
     650       49896 :   fd_bn254_fp2_sub( &r->el[0].el[0], &t[0], &a->el[0].el[0] );
     651       49896 :   fd_bn254_fp2_add( &r->el[0].el[0], &r->el[0].el[0], &r->el[0].el[0] );
     652       49896 :   fd_bn254_fp2_add( &r->el[0].el[0], &r->el[0].el[0], &t[0] );
     653       49896 :   fd_bn254_fp2_sub( &r->el[0].el[1], &t[2], &a->el[0].el[1] );
     654       49896 :   fd_bn254_fp2_add( &r->el[0].el[1], &r->el[0].el[1], &r->el[0].el[1] );
     655       49896 :   fd_bn254_fp2_add( &r->el[0].el[1], &r->el[0].el[1], &t[2] );
     656       49896 :   fd_bn254_fp2_sub( &r->el[0].el[2], &t[4], &a->el[0].el[2] );
     657       49896 :   fd_bn254_fp2_add( &r->el[0].el[2], &r->el[0].el[2], &r->el[0].el[2] );
     658       49896 :   fd_bn254_fp2_add( &r->el[0].el[2], &r->el[0].el[2], &t[4] );
     659             : 
     660       49896 :   fd_bn254_fp2_add( &r->el[1].el[0], &t[8], &a->el[1].el[0] );
     661       49896 :   fd_bn254_fp2_add( &r->el[1].el[0], &r->el[1].el[0], &r->el[1].el[0] );
     662       49896 :   fd_bn254_fp2_add( &r->el[1].el[0], &r->el[1].el[0], &t[8] );
     663       49896 :   fd_bn254_fp2_add( &r->el[1].el[1], &t[6], &a->el[1].el[1] );
     664       49896 :   fd_bn254_fp2_add( &r->el[1].el[1], &r->el[1].el[1], &r->el[1].el[1] );
     665       49896 :   fd_bn254_fp2_add( &r->el[1].el[1], &r->el[1].el[1], &t[6] );
     666       49896 :   fd_bn254_fp2_add( &r->el[1].el[2], &t[7], &a->el[1].el[2] );
     667       49896 :   fd_bn254_fp2_add( &r->el[1].el[2], &r->el[1].el[2], &r->el[1].el[2] );
     668       49896 :   fd_bn254_fp2_add( &r->el[1].el[2], &r->el[1].el[2], &t[7] );
     669       49896 :   return r;
     670       49896 : }
     671             : 
     672             : fd_bn254_fp12_t *
     673             : fd_bn254_fp12_inv( fd_bn254_fp12_t * r,
     674         264 :                    fd_bn254_fp12_t const * a ) {
     675             :   /* https://eprint.iacr.org/2010/354, Alg. 23 */
     676         264 :   fd_bn254_fp6_t t0[1], t1[1];
     677         264 :   fd_bn254_fp6_sqr( t0, &a->el[0] );
     678         264 :   fd_bn254_fp6_sqr( t1, &a->el[1] );
     679         264 :   fd_bn254_fp6_mul_by_gamma( t1, t1 );
     680         264 :   fd_bn254_fp6_sub( t0, t0, t1 );
     681         264 :   fd_bn254_fp6_inv( t1, t0 );
     682         264 :   fd_bn254_fp6_mul( &r->el[0], &a->el[0], t1 );
     683         264 :   fd_bn254_fp6_mul( &r->el[1], &a->el[1], t1 );
     684         264 :   fd_bn254_fp6_neg( &r->el[1], &r->el[1] );
     685         264 :   return r;
     686         264 : }
     687             : 
     688             : static inline fd_bn254_fp12_t *
     689             : fd_bn254_fp12_frob( fd_bn254_fp12_t * r,
     690         528 :                     fd_bn254_fp12_t const * a ) {
     691             :   /* https://eprint.iacr.org/2010/354, Alg. 28 */
     692         528 :   fd_bn254_fp2_t t[5];
     693             : 
     694             :   /* conj(g0) */
     695         528 :   fd_bn254_fp2_conj( &r->el[0].el[0], &a->el[0].el[0] );
     696         528 :   fd_bn254_fp2_conj( &t[0], &a->el[0].el[1] );
     697         528 :   fd_bn254_fp2_conj( &t[1], &a->el[0].el[2] );
     698         528 :   fd_bn254_fp2_conj( &t[2], &a->el[1].el[0] );
     699         528 :   fd_bn254_fp2_conj( &t[3], &a->el[1].el[1] );
     700         528 :   fd_bn254_fp2_conj( &t[4], &a->el[1].el[2] );
     701             : 
     702             :   /* conj(g1) * gamma_1,2 */
     703         528 :   fd_bn254_fp2_mul( &r->el[0].el[1], &t[0], &fd_bn254_const_frob_gamma1_mont[1] );
     704             : 
     705             :   /* conj(g2) * gamma_1,4 */
     706         528 :   fd_bn254_fp2_mul( &r->el[0].el[2], &t[1], &fd_bn254_const_frob_gamma1_mont[3] );
     707             : 
     708             :   /* conj(h0) * gamma_1,1 */
     709         528 :   fd_bn254_fp2_mul( &r->el[1].el[0], &t[2], &fd_bn254_const_frob_gamma1_mont[0] );
     710             : 
     711             :   /* conj(h1) * gamma_1,3 */
     712         528 :   fd_bn254_fp2_mul( &r->el[1].el[1], &t[3], &fd_bn254_const_frob_gamma1_mont[2] );
     713             : 
     714             :   /* conj(h2) * gamma_1,5 */
     715         528 :   fd_bn254_fp2_mul( &r->el[1].el[2], &t[4], &fd_bn254_const_frob_gamma1_mont[4] );
     716         528 :   return r;
     717         528 : }
     718             : 
     719             : static inline fd_bn254_fp12_t *
     720             : fd_bn254_fp12_frob2( fd_bn254_fp12_t * r,
     721         792 :                      fd_bn254_fp12_t const * a ) {
     722             :   /* https://eprint.iacr.org/2010/354, Alg. 29 */
     723             : 
     724             :   /* g0 */
     725         792 :   fd_bn254_fp2_set( &r->el[0].el[0], &a->el[0].el[0] );
     726             : 
     727             :   /* g1 * gamma_2,2 */
     728         792 :   fd_bn254_fp_mul( &r->el[0].el[1].el[0], &a->el[0].el[1].el[0], &fd_bn254_const_frob_gamma2_mont[1] );
     729         792 :   fd_bn254_fp_mul( &r->el[0].el[1].el[1], &a->el[0].el[1].el[1], &fd_bn254_const_frob_gamma2_mont[1] );
     730             : 
     731             :   /* g2 * gamma_2,4 */
     732         792 :   fd_bn254_fp_mul( &r->el[0].el[2].el[0], &a->el[0].el[2].el[0], &fd_bn254_const_frob_gamma2_mont[3] );
     733         792 :   fd_bn254_fp_mul( &r->el[0].el[2].el[1], &a->el[0].el[2].el[1], &fd_bn254_const_frob_gamma2_mont[3] );
     734             : 
     735             :   /* h0 * gamma_2,1 */
     736         792 :   fd_bn254_fp_mul( &r->el[1].el[0].el[0], &a->el[1].el[0].el[0], &fd_bn254_const_frob_gamma2_mont[0] );
     737         792 :   fd_bn254_fp_mul( &r->el[1].el[0].el[1], &a->el[1].el[0].el[1], &fd_bn254_const_frob_gamma2_mont[0] );
     738             : 
     739             :   /* h1 * gamma_2,3 */
     740         792 :   fd_bn254_fp_mul( &r->el[1].el[1].el[0], &a->el[1].el[1].el[0], &fd_bn254_const_frob_gamma2_mont[2] );
     741         792 :   fd_bn254_fp_mul( &r->el[1].el[1].el[1], &a->el[1].el[1].el[1], &fd_bn254_const_frob_gamma2_mont[2] );
     742             : 
     743             :   /* h2 * gamma_2,5 */
     744         792 :   fd_bn254_fp_mul( &r->el[1].el[2].el[0], &a->el[1].el[2].el[0], &fd_bn254_const_frob_gamma2_mont[4] );
     745         792 :   fd_bn254_fp_mul( &r->el[1].el[2].el[1], &a->el[1].el[2].el[1], &fd_bn254_const_frob_gamma2_mont[4] );
     746         792 :   return r;
     747         792 : }

Generated by: LCOV version 1.14