github.com/consensys/gnark-crypto@v0.14.0/ecc/bw6-756/internal/fptower/e3.go (about)

     1  // Copyright 2020 ConsenSys AG
     2  //
     3  // You may obtain a copy of the License at
     4  //
     5  //     http://www.apache.org/licenses/LICENSE-2.0
     6  //
     7  // Unless required by applicable law or agreed to in writing, software
     8  // distributed under the License is distributed on an "AS IS" BASIS,
     9  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    10  // See the License for the specific language governing permissions and
    11  // limitations under the License.
    12  
    13  package fptower
    14  
    15  import (
    16  	"github.com/consensys/gnark-crypto/ecc/bw6-756/fp"
    17  )
    18  
    19  // E3 is a degree-three finite field extension of fp3
    20  type E3 struct {
    21  	A0, A1, A2 fp.Element
    22  }
    23  
    24  // Equal returns true if z equals x, false otherwise
    25  // note this is more efficient than calling "z == x"
    26  func (z *E3) Equal(x *E3) bool {
    27  	return z.A0.Equal(&x.A0) && z.A1.Equal(&x.A1) && z.A2.Equal(&x.A2)
    28  }
    29  
    30  // SetString sets a E3 elmt from string
    31  func (z *E3) SetString(s1, s2, s3 string) *E3 {
    32  	z.A0.SetString(s1)
    33  	z.A1.SetString(s2)
    34  	z.A2.SetString(s3)
    35  	return z
    36  }
    37  
    38  // SetZero sets an E3 elmt to zero
    39  func (z *E3) SetZero() *E3 {
    40  	*z = E3{}
    41  	return z
    42  }
    43  
    44  // Clone returns a copy of self
    45  func (z *E3) Clone() *E3 {
    46  	return &E3{
    47  		A0: z.A0,
    48  		A1: z.A1,
    49  		A2: z.A2,
    50  	}
    51  }
    52  
    53  // Set Sets a E3 elmt form another E3 elmt
    54  func (z *E3) Set(x *E3) *E3 {
    55  	*z = *x
    56  	return z
    57  }
    58  
    59  // SetOne sets z to 1 in Montgomery form and returns z
    60  func (z *E3) SetOne() *E3 {
    61  	z.A0.SetOne()
    62  	z.A1.SetZero()
    63  	z.A2.SetZero()
    64  	return z
    65  }
    66  
    67  // SetRandom sets z to a random elmt
    68  func (z *E3) SetRandom() (*E3, error) {
    69  	if _, err := z.A0.SetRandom(); err != nil {
    70  		return nil, err
    71  	}
    72  	if _, err := z.A1.SetRandom(); err != nil {
    73  		return nil, err
    74  	}
    75  	if _, err := z.A2.SetRandom(); err != nil {
    76  		return nil, err
    77  	}
    78  	return z, nil
    79  }
    80  
    81  // IsZero returns true if z is zero, false otherwise
    82  func (z *E3) IsZero() bool {
    83  	return z.A0.IsZero() && z.A1.IsZero() && z.A2.IsZero()
    84  }
    85  
    86  // IsOne returns true if z is one, false otherwise
    87  func (z *E3) IsOne() bool {
    88  	return z.A0.IsOne() && z.A1.IsZero() && z.A2.IsZero()
    89  }
    90  
    91  // Neg negates the E3 number
    92  func (z *E3) Neg(x *E3) *E3 {
    93  	z.A0.Neg(&x.A0)
    94  	z.A1.Neg(&x.A1)
    95  	z.A2.Neg(&x.A2)
    96  	return z
    97  }
    98  
    99  // Add adds two elements of E3
   100  func (z *E3) Add(x, y *E3) *E3 {
   101  	z.A0.Add(&x.A0, &y.A0)
   102  	z.A1.Add(&x.A1, &y.A1)
   103  	z.A2.Add(&x.A2, &y.A2)
   104  	return z
   105  }
   106  
   107  // Sub subtracts two elements of E3
   108  func (z *E3) Sub(x, y *E3) *E3 {
   109  	z.A0.Sub(&x.A0, &y.A0)
   110  	z.A1.Sub(&x.A1, &y.A1)
   111  	z.A2.Sub(&x.A2, &y.A2)
   112  	return z
   113  }
   114  
   115  // Double doubles an element in E3
   116  func (z *E3) Double(x *E3) *E3 {
   117  	z.A0.Double(&x.A0)
   118  	z.A1.Double(&x.A1)
   119  	z.A2.Double(&x.A2)
   120  	return z
   121  }
   122  
   123  // String puts E3 elmt in string form
   124  func (z *E3) String() string {
   125  	return (z.A0.String() + "+(" + z.A1.String() + ")*u+(" + z.A2.String() + ")*u**2")
   126  }
   127  
   128  // MulByElement multiplies an element in E3 by an element in fp
   129  func (z *E3) MulByElement(x *E3, y *fp.Element) *E3 {
   130  	_y := *y
   131  	z.A0.Mul(&x.A0, &_y)
   132  	z.A1.Mul(&x.A1, &_y)
   133  	z.A2.Mul(&x.A2, &_y)
   134  	return z
   135  }
   136  
   137  // MulBy12 multiplication by sparse element (0,b1,b2)
   138  func (x *E3) MulBy12(b1, b2 *fp.Element) *E3 {
   139  	var t1, t2, c0, tmp, c1, c2 fp.Element
   140  	t1.Mul(&x.A1, b1)
   141  	t2.Mul(&x.A2, b2)
   142  	c0.Add(&x.A1, &x.A2)
   143  	tmp.Add(b1, b2)
   144  	c0.Mul(&c0, &tmp)
   145  	c0.Sub(&c0, &t1)
   146  	c0.Sub(&c0, &t2)
   147  	c0.MulByNonResidue(&c0)
   148  	c1.Add(&x.A0, &x.A1)
   149  	c1.Mul(&c1, b1)
   150  	c1.Sub(&c1, &t1)
   151  	tmp.MulByNonResidue(&t2)
   152  	c1.Add(&c1, &tmp)
   153  	tmp.Add(&x.A0, &x.A2)
   154  	c2.Mul(b2, &tmp)
   155  	c2.Sub(&c2, &t2)
   156  	c2.Add(&c2, &t1)
   157  
   158  	x.A0 = c0
   159  	x.A1 = c1
   160  	x.A2 = c2
   161  
   162  	return x
   163  }
   164  
   165  // MulBy01 multiplication by sparse element (c0,c1,0)
   166  func (z *E3) MulBy01(c0, c1 *fp.Element) *E3 {
   167  
   168  	var a, b, tmp, t0, t1, t2 fp.Element
   169  
   170  	a.Mul(&z.A0, c0)
   171  	b.Mul(&z.A1, c1)
   172  
   173  	tmp.Add(&z.A1, &z.A2)
   174  	t0.Mul(c1, &tmp)
   175  	t0.Sub(&t0, &b)
   176  	t0.MulByNonResidue(&t0)
   177  	t0.Add(&t0, &a)
   178  
   179  	tmp.Add(&z.A0, &z.A2)
   180  	t2.Mul(c0, &tmp)
   181  	t2.Sub(&t2, &a)
   182  	t2.Add(&t2, &b)
   183  
   184  	t1.Add(c0, c1)
   185  	tmp.Add(&z.A0, &z.A1)
   186  	t1.Mul(&t1, &tmp)
   187  	t1.Sub(&t1, &a)
   188  	t1.Sub(&t1, &b)
   189  
   190  	z.A0.Set(&t0)
   191  	z.A1.Set(&t1)
   192  	z.A2.Set(&t2)
   193  
   194  	return z
   195  }
   196  
   197  // MulBy1 multiplication of E6 by sparse element (0, c1, 0)
   198  func (z *E3) MulBy1(c1 *fp.Element) *E3 {
   199  
   200  	var b, tmp, t0, t1 fp.Element
   201  	b.Mul(&z.A1, c1)
   202  
   203  	tmp.Add(&z.A1, &z.A2)
   204  	t0.Mul(c1, &tmp)
   205  	t0.Sub(&t0, &b)
   206  	t0.MulByNonResidue(&t0)
   207  
   208  	tmp.Add(&z.A0, &z.A1)
   209  	t1.Mul(c1, &tmp)
   210  	t1.Sub(&t1, &b)
   211  
   212  	z.A0.Set(&t0)
   213  	z.A1.Set(&t1)
   214  	z.A2.Set(&b)
   215  
   216  	return z
   217  }
   218  
   219  // Mul sets z to the E3-product of x,y, returns z
   220  func (z *E3) Mul(x, y *E3) *E3 {
   221  	// Karatsuba method for cubic extensions
   222  	// https://eprint.iacr.org/2006/471.pdf (section 4)
   223  	var t0, t1, t2, c0, c1, c2, tmp fp.Element
   224  	t0.Mul(&x.A0, &y.A0)
   225  	t1.Mul(&x.A1, &y.A1)
   226  	t2.Mul(&x.A2, &y.A2)
   227  
   228  	c0.Add(&x.A1, &x.A2)
   229  	tmp.Add(&y.A1, &y.A2)
   230  	c0.Mul(&c0, &tmp).Sub(&c0, &t1).Sub(&c0, &t2).MulByNonResidue(&c0)
   231  
   232  	tmp.Add(&x.A0, &x.A2)
   233  	c2.Add(&y.A0, &y.A2).Mul(&c2, &tmp).Sub(&c2, &t0).Sub(&c2, &t2)
   234  
   235  	c1.Add(&x.A0, &x.A1)
   236  	tmp.Add(&y.A0, &y.A1)
   237  	c1.Mul(&c1, &tmp).Sub(&c1, &t0).Sub(&c1, &t1)
   238  	t2.MulByNonResidue(&t2)
   239  
   240  	z.A0.Add(&c0, &t0)
   241  	z.A1.Add(&c1, &t2)
   242  	z.A2.Add(&c2, &t1)
   243  
   244  	return z
   245  }
   246  
   247  // MulAssign sets z to the E3-product of z,y, returns z
   248  func (z *E3) MulAssign(x *E3) *E3 {
   249  	return z.Mul(z, x)
   250  }
   251  
   252  // Square sets z to the E3-product of x,x, returns z
   253  func (z *E3) Square(x *E3) *E3 {
   254  
   255  	// Algorithm 16 from https://eprint.iacr.org/2010/354.pdf
   256  	var c4, c5, c1, c2, c3, c0, c6 fp.Element
   257  
   258  	c6.Double(&x.A1)
   259  	c4.Mul(&x.A0, &c6) // x.A0 * xA1 * 2
   260  	c5.Square(&x.A2)
   261  	c1.MulByNonResidue(&c5).Add(&c1, &c4)
   262  	c2.Sub(&c4, &c5)
   263  
   264  	c3.Square(&x.A0)
   265  	c4.Sub(&x.A0, &x.A1).Add(&c4, &x.A2)
   266  	c5.Mul(&c6, &x.A2) // x.A1 * xA2 * 2
   267  	c4.Square(&c4)
   268  	c0.MulByNonResidue(&c5)
   269  	c4.Add(&c4, &c5).Sub(&c4, &c3)
   270  
   271  	z.A0.Add(&c0, &c3)
   272  	z.A1 = c1
   273  	z.A2.Add(&c2, &c4)
   274  
   275  	return z
   276  }
   277  
   278  // MulByNonResidue mul x by (0,1,0)
   279  func (z *E3) MulByNonResidue(x *E3) *E3 {
   280  	z.A2, z.A1, z.A0 = x.A1, x.A0, x.A2
   281  	z.A0.MulByNonResidue(&z.A0)
   282  	return z
   283  }
   284  
   285  // Inverse an element in E3
   286  //
   287  // if x == 0, sets and returns z = x
   288  func (z *E3) Inverse(x *E3) *E3 {
   289  	// Algorithm 17 from https://eprint.iacr.org/2010/354.pdf
   290  	// step 9 is wrong in the paper it's t1-t4
   291  	var t0, t1, t2, t3, t4, t5, t6, c0, c1, c2, d1, d2 fp.Element
   292  	t0.Square(&x.A0)
   293  	t1.Square(&x.A1)
   294  	t2.Square(&x.A2)
   295  	t3.Mul(&x.A0, &x.A1)
   296  	t4.Mul(&x.A0, &x.A2)
   297  	t5.Mul(&x.A1, &x.A2)
   298  	c0.MulByNonResidue(&t5).Neg(&c0).Add(&c0, &t0)
   299  	c1.MulByNonResidue(&t2).Sub(&c1, &t3)
   300  	c2.Sub(&t1, &t4)
   301  	t6.Mul(&x.A0, &c0)
   302  	d1.Mul(&x.A2, &c1)
   303  	d2.Mul(&x.A1, &c2)
   304  	d1.Add(&d1, &d2).MulByNonResidue(&d1)
   305  	t6.Add(&t6, &d1)
   306  	t6.Inverse(&t6)
   307  	z.A0.Mul(&c0, &t6)
   308  	z.A1.Mul(&c1, &t6)
   309  	z.A2.Mul(&c2, &t6)
   310  
   311  	return z
   312  }
   313  
   314  // BatchInvertE3 returns a new slice with every element in a inverted.
   315  // It uses Montgomery batch inversion trick.
   316  //
   317  // if a[i] == 0, returns result[i] = a[i]
   318  func BatchInvertE3(a []E3) []E3 {
   319  	res := make([]E3, len(a))
   320  	if len(a) == 0 {
   321  		return res
   322  	}
   323  
   324  	zeroes := make([]bool, len(a))
   325  	var accumulator E3
   326  	accumulator.SetOne()
   327  
   328  	for i := 0; i < len(a); i++ {
   329  		if a[i].IsZero() {
   330  			zeroes[i] = true
   331  			continue
   332  		}
   333  		res[i].Set(&accumulator)
   334  		accumulator.Mul(&accumulator, &a[i])
   335  	}
   336  
   337  	accumulator.Inverse(&accumulator)
   338  
   339  	for i := len(a) - 1; i >= 0; i-- {
   340  		if zeroes[i] {
   341  			continue
   342  		}
   343  		res[i].Mul(&res[i], &accumulator)
   344  		accumulator.Mul(&accumulator, &a[i])
   345  	}
   346  
   347  	return res
   348  }