github.com/cloudflare/circl@v1.5.0/ecc/bls12381/ff/fp12cubic.go (about)

     1  package ff
     2  
     3  import "fmt"
     4  
     5  // Fp12Cubic represents elements of Fp4[w]/w^3-t
     6  type Fp12Cubic [3]Fp4
     7  
     8  // LineValue a represents a[0]+a[1]*w^2+a[2]*w^3, with all values in Fp2.
     9  // This lets us shave off a number of Fp2 multiplications.
    10  type LineValue [3]Fp2
    11  
    12  func (z Fp12Cubic) String() string {
    13  	return fmt.Sprintf("%s + ( %s )*w + ( %s )*w^2", z[0], z[1], z[2])
    14  }
    15  
    16  func (z Fp12Cubic) IsEqual(x *Fp12Cubic) int {
    17  	return z[0].IsEqual(&x[0]) & z[1].IsEqual(&x[1]) & z[2].IsEqual(&x[2])
    18  }
    19  
    20  func (z *Fp12Cubic) FromFp12(x *Fp12) {
    21  	// To understand this function, write everything in Fp2[w]/(w^6-(u+1)).
    22  	// v = w^2
    23  	// t = w^3
    24  	z[0][0] = x[0][0] // w^0
    25  	z[1][0] = x[1][0] // w^1
    26  	z[2][0] = x[0][1] // w^2
    27  	z[0][1] = x[1][1] // w^3
    28  	z[1][1] = x[0][2] // w^4
    29  	z[2][1] = x[1][2] // w^5
    30  }
    31  
    32  func (z *Fp12) FromFp12Cubic(x *Fp12Cubic) {
    33  	z[0][0] = x[0][0] // w^0
    34  	z[1][0] = x[1][0] // w^1
    35  	z[0][1] = x[2][0] // w^2
    36  	z[1][1] = x[0][1] // w^3
    37  	z[0][2] = x[1][1] // w^4
    38  	z[1][2] = x[2][1] // w^5
    39  }
    40  
    41  func (z *Fp12Cubic) Add(x *Fp12Cubic, y *Fp12Cubic) {
    42  	z[0].Add(&x[0], &y[0])
    43  	z[1].Add(&x[1], &y[1])
    44  	z[2].Add(&x[2], &y[2])
    45  }
    46  
    47  func (z *Fp12Cubic) SetOne() {
    48  	z[0].SetOne()
    49  	z[1] = Fp4{}
    50  	z[2] = Fp4{}
    51  }
    52  
    53  func (z *Fp12Cubic) Mul(x *Fp12Cubic, y *Fp12Cubic) {
    54  	// This is a Karatsuba like technique: compute x_iy_i, then
    55  	// subtract the terms from expressions like (x0+x1)(y0+y1).
    56  	// See Multiplication and Squaring in Pairing Friendly Fields
    57  	// for more.
    58  	var v0, v1, v2, p0, p1, p2, tx, ty Fp4
    59  	v0.Mul(&x[0], &y[0])
    60  	v1.Mul(&x[1], &y[1])
    61  	v2.Mul(&x[2], &y[2])
    62  
    63  	tx.Add(&x[1], &x[2])
    64  	ty.Add(&y[1], &y[2])
    65  	p0.Mul(&tx, &ty)
    66  
    67  	tx.Add(&x[0], &x[1])
    68  	ty.Add(&y[0], &y[1])
    69  	p1.Mul(&tx, &ty)
    70  
    71  	tx.Add(&x[0], &x[2])
    72  	ty.Add(&y[0], &y[2])
    73  	p2.Mul(&tx, &ty)
    74  
    75  	z[0].Sub(&p0, &v1)
    76  	z[0].Sub(&z[0], &v2)
    77  	z[0].mulT(&z[0])
    78  	z[0].Add(&z[0], &v0)
    79  
    80  	z[1].Sub(&p1, &v0)
    81  	z[1].Sub(&z[1], &v1)
    82  	tx.mulT(&v2)
    83  	z[1].Add(&z[1], &tx)
    84  
    85  	z[2].Sub(&p2, &v0)
    86  	z[2].Add(&z[2], &v1)
    87  	z[2].Sub(&z[2], &v2)
    88  }
    89  
    90  func (z *Fp12Cubic) Sqr(x *Fp12Cubic) {
    91  	// The Chung-Hasan asymmetric squaring formula.
    92  	// We keep the same notation as in Multiplication
    93  	// and Squaring on Pairing-Friendly Fields to make
    94  	// it easier to compare.
    95  
    96  	var s0, s1, s2, s3, s4, t Fp4
    97  	s0.Sqr(&x[0]) // x0^2
    98  	s1.Mul(&x[0], &x[1])
    99  	s1.Add(&s1, &s1) // 2x0x1
   100  	t.Add(&x[0], &x[2])
   101  	t.Sub(&t, &x[1])
   102  	s2.Sqr(&t) // (x0-x1+x2)^2
   103  	s3.Mul(&x[1], &x[2])
   104  	s3.Add(&s3, &s3) // 2x1x2
   105  	s4.Sqr(&x[2])    // x2^2
   106  
   107  	z[0].mulT(&s3)
   108  	z[0].Add(&z[0], &s0)
   109  
   110  	z[1].mulT(&s4)
   111  	z[1].Add(&z[1], &s1)
   112  
   113  	z[2].Add(&s1, &s2)
   114  	z[2].Add(&z[2], &s3)
   115  	z[2].Sub(&z[2], &s0)
   116  	z[2].Sub(&z[2], &s4)
   117  }
   118  
   119  func (z *Fp12Cubic) MulLine(x *Fp12Cubic, y *LineValue) {
   120  	// Values produced by evaluating a line function
   121  	// do not have a linear term, and the quadratic term is
   122  	// in Fp2.
   123  
   124  	// We copy the Mul method, but remove any multiplies by y1,
   125  	// and strength reduce multiplies by y2.
   126  	var y0 Fp4
   127  	var y2 Fp2
   128  	var v0, v2, p0, p1, p2, tx, ty Fp4
   129  
   130  	y0[0] = y[0]
   131  	y0[1] = y[2]
   132  	y2 = y[1]
   133  
   134  	v0.Mul(&x[0], &y0)
   135  	v2.mulSubfield(&x[2], &y2)
   136  
   137  	tx.Add(&x[1], &x[2])
   138  	p0.mulSubfield(&tx, &y2)
   139  
   140  	tx.Add(&x[0], &x[1])
   141  	p1.Mul(&tx, &y0)
   142  
   143  	tx.Add(&x[0], &x[2])
   144  	ty = y0
   145  	ty[0].Add(&ty[0], &y2)
   146  	p2.Mul(&tx, &ty)
   147  
   148  	z[0].Sub(&p0, &v2)
   149  	z[0].mulT(&z[0])
   150  	z[0].Add(&z[0], &v0)
   151  
   152  	z[1].Sub(&p1, &v0)
   153  	tx.mulT(&v2)
   154  	z[1].Add(&z[1], &tx)
   155  
   156  	z[2].Sub(&p2, &v0)
   157  	z[2].Sub(&z[2], &v2)
   158  }
   159  
   160  func (z *LineValue) IsZero() int {
   161  	return z[0].IsZero() & z[1].IsZero() & z[2].IsZero()
   162  }
   163  
   164  func (z *LineValue) SetOne() {
   165  	z[0].SetOne()
   166  	z[1] = Fp2{}
   167  	z[2] = Fp2{}
   168  }