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 }