github.com/consensys/gnark-crypto@v0.14.0/ecc/secp256k1/fr/element_ops_purego.go (about)

     1  // Copyright 2020 ConsenSys Software Inc.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  // Code generated by consensys/gnark-crypto DO NOT EDIT
    16  
    17  package fr
    18  
    19  import "math/bits"
    20  
    21  // MulBy3 x *= 3 (mod q)
    22  func MulBy3(x *Element) {
    23  	_x := *x
    24  	x.Double(x).Add(x, &_x)
    25  }
    26  
    27  // MulBy5 x *= 5 (mod q)
    28  func MulBy5(x *Element) {
    29  	_x := *x
    30  	x.Double(x).Double(x).Add(x, &_x)
    31  }
    32  
    33  // MulBy13 x *= 13 (mod q)
    34  func MulBy13(x *Element) {
    35  	var y = Element{
    36  		4778656589038923699,
    37  		9592324472628567287,
    38  		16,
    39  		0,
    40  	}
    41  	x.Mul(x, &y)
    42  }
    43  
    44  // Butterfly sets
    45  //
    46  //	a = a + b (mod q)
    47  //	b = a - b (mod q)
    48  func Butterfly(a, b *Element) {
    49  	_butterflyGeneric(a, b)
    50  }
    51  
    52  func fromMont(z *Element) {
    53  	_fromMontGeneric(z)
    54  }
    55  
    56  func reduce(z *Element) {
    57  	_reduceGeneric(z)
    58  }
    59  
    60  // Mul z = x * y (mod q)
    61  func (z *Element) Mul(x, y *Element) *Element {
    62  
    63  	// Implements CIOS multiplication -- section 2.3.2 of Tolga Acar's thesis
    64  	// https://www.microsoft.com/en-us/research/wp-content/uploads/1998/06/97Acar.pdf
    65  	//
    66  	// The algorithm:
    67  	//
    68  	// for i=0 to N-1
    69  	// 		C := 0
    70  	// 		for j=0 to N-1
    71  	// 			(C,t[j]) := t[j] + x[j]*y[i] + C
    72  	// 		(t[N+1],t[N]) := t[N] + C
    73  	//
    74  	// 		C := 0
    75  	// 		m := t[0]*q'[0] mod D
    76  	// 		(C,_) := t[0] + m*q[0]
    77  	// 		for j=1 to N-1
    78  	// 			(C,t[j-1]) := t[j] + m*q[j] + C
    79  	//
    80  	// 		(C,t[N-1]) := t[N] + C
    81  	// 		t[N] := t[N+1] + C
    82  	//
    83  	// → N is the number of machine words needed to store the modulus q
    84  	// → D is the word size. For example, on a 64-bit architecture D is 2	64
    85  	// → x[i], y[i], q[i] is the ith word of the numbers x,y,q
    86  	// → q'[0] is the lowest word of the number -q⁻¹ mod r. This quantity is pre-computed, as it does not depend on the inputs.
    87  	// → t is a temporary array of size N+2
    88  	// → C, S are machine words. A pair (C,S) refers to (hi-bits, lo-bits) of a two-word number
    89  
    90  	var t [5]uint64
    91  	var D uint64
    92  	var m, C uint64
    93  	// -----------------------------------
    94  	// First loop
    95  
    96  	C, t[0] = bits.Mul64(y[0], x[0])
    97  	C, t[1] = madd1(y[0], x[1], C)
    98  	C, t[2] = madd1(y[0], x[2], C)
    99  	C, t[3] = madd1(y[0], x[3], C)
   100  
   101  	t[4], D = bits.Add64(t[4], C, 0)
   102  
   103  	// m = t[0]n'[0] mod W
   104  	m = t[0] * qInvNeg
   105  
   106  	// -----------------------------------
   107  	// Second loop
   108  	C = madd0(m, q0, t[0])
   109  	C, t[0] = madd2(m, q1, t[1], C)
   110  	C, t[1] = madd2(m, q2, t[2], C)
   111  	C, t[2] = madd2(m, q3, t[3], C)
   112  
   113  	t[3], C = bits.Add64(t[4], C, 0)
   114  	t[4], _ = bits.Add64(0, D, C)
   115  	// -----------------------------------
   116  	// First loop
   117  
   118  	C, t[0] = madd1(y[1], x[0], t[0])
   119  	C, t[1] = madd2(y[1], x[1], t[1], C)
   120  	C, t[2] = madd2(y[1], x[2], t[2], C)
   121  	C, t[3] = madd2(y[1], x[3], t[3], C)
   122  
   123  	t[4], D = bits.Add64(t[4], C, 0)
   124  
   125  	// m = t[0]n'[0] mod W
   126  	m = t[0] * qInvNeg
   127  
   128  	// -----------------------------------
   129  	// Second loop
   130  	C = madd0(m, q0, t[0])
   131  	C, t[0] = madd2(m, q1, t[1], C)
   132  	C, t[1] = madd2(m, q2, t[2], C)
   133  	C, t[2] = madd2(m, q3, t[3], C)
   134  
   135  	t[3], C = bits.Add64(t[4], C, 0)
   136  	t[4], _ = bits.Add64(0, D, C)
   137  	// -----------------------------------
   138  	// First loop
   139  
   140  	C, t[0] = madd1(y[2], x[0], t[0])
   141  	C, t[1] = madd2(y[2], x[1], t[1], C)
   142  	C, t[2] = madd2(y[2], x[2], t[2], C)
   143  	C, t[3] = madd2(y[2], x[3], t[3], C)
   144  
   145  	t[4], D = bits.Add64(t[4], C, 0)
   146  
   147  	// m = t[0]n'[0] mod W
   148  	m = t[0] * qInvNeg
   149  
   150  	// -----------------------------------
   151  	// Second loop
   152  	C = madd0(m, q0, t[0])
   153  	C, t[0] = madd2(m, q1, t[1], C)
   154  	C, t[1] = madd2(m, q2, t[2], C)
   155  	C, t[2] = madd2(m, q3, t[3], C)
   156  
   157  	t[3], C = bits.Add64(t[4], C, 0)
   158  	t[4], _ = bits.Add64(0, D, C)
   159  	// -----------------------------------
   160  	// First loop
   161  
   162  	C, t[0] = madd1(y[3], x[0], t[0])
   163  	C, t[1] = madd2(y[3], x[1], t[1], C)
   164  	C, t[2] = madd2(y[3], x[2], t[2], C)
   165  	C, t[3] = madd2(y[3], x[3], t[3], C)
   166  
   167  	t[4], D = bits.Add64(t[4], C, 0)
   168  
   169  	// m = t[0]n'[0] mod W
   170  	m = t[0] * qInvNeg
   171  
   172  	// -----------------------------------
   173  	// Second loop
   174  	C = madd0(m, q0, t[0])
   175  	C, t[0] = madd2(m, q1, t[1], C)
   176  	C, t[1] = madd2(m, q2, t[2], C)
   177  	C, t[2] = madd2(m, q3, t[3], C)
   178  
   179  	t[3], C = bits.Add64(t[4], C, 0)
   180  	t[4], _ = bits.Add64(0, D, C)
   181  
   182  	if t[4] != 0 {
   183  		// we need to reduce, we have a result on 5 words
   184  		var b uint64
   185  		z[0], b = bits.Sub64(t[0], q0, 0)
   186  		z[1], b = bits.Sub64(t[1], q1, b)
   187  		z[2], b = bits.Sub64(t[2], q2, b)
   188  		z[3], _ = bits.Sub64(t[3], q3, b)
   189  		return z
   190  	}
   191  
   192  	// copy t into z
   193  	z[0] = t[0]
   194  	z[1] = t[1]
   195  	z[2] = t[2]
   196  	z[3] = t[3]
   197  
   198  	// if z ⩾ q → z -= q
   199  	if !z.smallerThanModulus() {
   200  		var b uint64
   201  		z[0], b = bits.Sub64(z[0], q0, 0)
   202  		z[1], b = bits.Sub64(z[1], q1, b)
   203  		z[2], b = bits.Sub64(z[2], q2, b)
   204  		z[3], _ = bits.Sub64(z[3], q3, b)
   205  	}
   206  	return z
   207  }
   208  
   209  // Square z = x * x (mod q)
   210  func (z *Element) Square(x *Element) *Element {
   211  	// see Mul for algorithm documentation
   212  
   213  	var t [5]uint64
   214  	var D uint64
   215  	var m, C uint64
   216  	// -----------------------------------
   217  	// First loop
   218  
   219  	C, t[0] = bits.Mul64(x[0], x[0])
   220  	C, t[1] = madd1(x[0], x[1], C)
   221  	C, t[2] = madd1(x[0], x[2], C)
   222  	C, t[3] = madd1(x[0], x[3], C)
   223  
   224  	t[4], D = bits.Add64(t[4], C, 0)
   225  
   226  	// m = t[0]n'[0] mod W
   227  	m = t[0] * qInvNeg
   228  
   229  	// -----------------------------------
   230  	// Second loop
   231  	C = madd0(m, q0, t[0])
   232  	C, t[0] = madd2(m, q1, t[1], C)
   233  	C, t[1] = madd2(m, q2, t[2], C)
   234  	C, t[2] = madd2(m, q3, t[3], C)
   235  
   236  	t[3], C = bits.Add64(t[4], C, 0)
   237  	t[4], _ = bits.Add64(0, D, C)
   238  	// -----------------------------------
   239  	// First loop
   240  
   241  	C, t[0] = madd1(x[1], x[0], t[0])
   242  	C, t[1] = madd2(x[1], x[1], t[1], C)
   243  	C, t[2] = madd2(x[1], x[2], t[2], C)
   244  	C, t[3] = madd2(x[1], x[3], t[3], C)
   245  
   246  	t[4], D = bits.Add64(t[4], C, 0)
   247  
   248  	// m = t[0]n'[0] mod W
   249  	m = t[0] * qInvNeg
   250  
   251  	// -----------------------------------
   252  	// Second loop
   253  	C = madd0(m, q0, t[0])
   254  	C, t[0] = madd2(m, q1, t[1], C)
   255  	C, t[1] = madd2(m, q2, t[2], C)
   256  	C, t[2] = madd2(m, q3, t[3], C)
   257  
   258  	t[3], C = bits.Add64(t[4], C, 0)
   259  	t[4], _ = bits.Add64(0, D, C)
   260  	// -----------------------------------
   261  	// First loop
   262  
   263  	C, t[0] = madd1(x[2], x[0], t[0])
   264  	C, t[1] = madd2(x[2], x[1], t[1], C)
   265  	C, t[2] = madd2(x[2], x[2], t[2], C)
   266  	C, t[3] = madd2(x[2], x[3], t[3], C)
   267  
   268  	t[4], D = bits.Add64(t[4], C, 0)
   269  
   270  	// m = t[0]n'[0] mod W
   271  	m = t[0] * qInvNeg
   272  
   273  	// -----------------------------------
   274  	// Second loop
   275  	C = madd0(m, q0, t[0])
   276  	C, t[0] = madd2(m, q1, t[1], C)
   277  	C, t[1] = madd2(m, q2, t[2], C)
   278  	C, t[2] = madd2(m, q3, t[3], C)
   279  
   280  	t[3], C = bits.Add64(t[4], C, 0)
   281  	t[4], _ = bits.Add64(0, D, C)
   282  	// -----------------------------------
   283  	// First loop
   284  
   285  	C, t[0] = madd1(x[3], x[0], t[0])
   286  	C, t[1] = madd2(x[3], x[1], t[1], C)
   287  	C, t[2] = madd2(x[3], x[2], t[2], C)
   288  	C, t[3] = madd2(x[3], x[3], t[3], C)
   289  
   290  	t[4], D = bits.Add64(t[4], C, 0)
   291  
   292  	// m = t[0]n'[0] mod W
   293  	m = t[0] * qInvNeg
   294  
   295  	// -----------------------------------
   296  	// Second loop
   297  	C = madd0(m, q0, t[0])
   298  	C, t[0] = madd2(m, q1, t[1], C)
   299  	C, t[1] = madd2(m, q2, t[2], C)
   300  	C, t[2] = madd2(m, q3, t[3], C)
   301  
   302  	t[3], C = bits.Add64(t[4], C, 0)
   303  	t[4], _ = bits.Add64(0, D, C)
   304  
   305  	if t[4] != 0 {
   306  		// we need to reduce, we have a result on 5 words
   307  		var b uint64
   308  		z[0], b = bits.Sub64(t[0], q0, 0)
   309  		z[1], b = bits.Sub64(t[1], q1, b)
   310  		z[2], b = bits.Sub64(t[2], q2, b)
   311  		z[3], _ = bits.Sub64(t[3], q3, b)
   312  		return z
   313  	}
   314  
   315  	// copy t into z
   316  	z[0] = t[0]
   317  	z[1] = t[1]
   318  	z[2] = t[2]
   319  	z[3] = t[3]
   320  
   321  	// if z ⩾ q → z -= q
   322  	if !z.smallerThanModulus() {
   323  		var b uint64
   324  		z[0], b = bits.Sub64(z[0], q0, 0)
   325  		z[1], b = bits.Sub64(z[1], q1, b)
   326  		z[2], b = bits.Sub64(z[2], q2, b)
   327  		z[3], _ = bits.Sub64(z[3], q3, b)
   328  	}
   329  	return z
   330  }