github.com/cloudflare/circl@v1.5.0/dh/csidh/fp511_generic.go (about)

     1  package csidh
     2  
     3  import "math/bits"
     4  
     5  // mul576 implements schoolbook multiplication of
     6  // 64x512-bit integer. Returns result modulo 2^512.
     7  // r = m1*m2.
     8  func mul512Generic(r, m1 *fp, m2 uint64) {
     9  	var c, h, l uint64
    10  
    11  	c, r[0] = bits.Mul64(m2, m1[0])
    12  
    13  	h, l = bits.Mul64(m2, m1[1])
    14  	r[1], c = bits.Add64(l, c, 0)
    15  	c = h + c
    16  
    17  	h, l = bits.Mul64(m2, m1[2])
    18  	r[2], c = bits.Add64(l, c, 0)
    19  	c = h + c
    20  
    21  	h, l = bits.Mul64(m2, m1[3])
    22  	r[3], c = bits.Add64(l, c, 0)
    23  	c = h + c
    24  
    25  	h, l = bits.Mul64(m2, m1[4])
    26  	r[4], c = bits.Add64(l, c, 0)
    27  	c = h + c
    28  
    29  	h, l = bits.Mul64(m2, m1[5])
    30  	r[5], c = bits.Add64(l, c, 0)
    31  	c = h + c
    32  
    33  	h, l = bits.Mul64(m2, m1[6])
    34  	r[6], c = bits.Add64(l, c, 0)
    35  	c = h + c
    36  
    37  	_, l = bits.Mul64(m2, m1[7])
    38  	r[7], _ = bits.Add64(l, c, 0)
    39  }
    40  
    41  // mul576 implements schoolbook multiplication of
    42  // 64x512-bit integer. Returns 576-bit result of
    43  // multiplication.
    44  // r = m1*m2.
    45  func mul576Generic(r *[9]uint64, m1 *fp, m2 uint64) {
    46  	var c, h, l uint64
    47  
    48  	c, r[0] = bits.Mul64(m2, m1[0])
    49  
    50  	h, l = bits.Mul64(m2, m1[1])
    51  	r[1], c = bits.Add64(l, c, 0)
    52  	c = h + c
    53  
    54  	h, l = bits.Mul64(m2, m1[2])
    55  	r[2], c = bits.Add64(l, c, 0)
    56  	c = h + c
    57  
    58  	h, l = bits.Mul64(m2, m1[3])
    59  	r[3], c = bits.Add64(l, c, 0)
    60  	c = h + c
    61  
    62  	h, l = bits.Mul64(m2, m1[4])
    63  	r[4], c = bits.Add64(l, c, 0)
    64  	c = h + c
    65  
    66  	h, l = bits.Mul64(m2, m1[5])
    67  	r[5], c = bits.Add64(l, c, 0)
    68  	c = h + c
    69  
    70  	h, l = bits.Mul64(m2, m1[6])
    71  	r[6], c = bits.Add64(l, c, 0)
    72  	c = h + c
    73  
    74  	h, l = bits.Mul64(m2, m1[7])
    75  	r[7], c = bits.Add64(l, c, 0)
    76  	r[8], c = bits.Add64(h, c, 0)
    77  	r[8] += c
    78  }
    79  
    80  // cswap512 implements constant time swap operation.
    81  // If choice = 0, leave x,y unchanged. If choice = 1, set x,y = y,x.
    82  // If choice is neither 0 nor 1 then behaviour is undefined.
    83  func cswap512Generic(x, y *fp, choice uint8) {
    84  	var tmp uint64
    85  	mask64 := 0 - uint64(choice)
    86  
    87  	for i := 0; i < numWords; i++ {
    88  		tmp = mask64 & (x[i] ^ y[i])
    89  		x[i] = tmp ^ x[i]
    90  		y[i] = tmp ^ y[i]
    91  	}
    92  }
    93  
    94  // mulRdc performs montgomery multiplication r = x * y mod P.
    95  // Returned result r is already reduced and in Montgomery domain.
    96  func mulRdcGeneric(r, x, y *fp) {
    97  	var t fp
    98  	var c uint64
    99  
   100  	mulGeneric(r, x, y)
   101  
   102  	// if p <= r < 2p then r = r-p
   103  	t[0], c = bits.Sub64(r[0], p[0], 0)
   104  	t[1], c = bits.Sub64(r[1], p[1], c)
   105  	t[2], c = bits.Sub64(r[2], p[2], c)
   106  	t[3], c = bits.Sub64(r[3], p[3], c)
   107  	t[4], c = bits.Sub64(r[4], p[4], c)
   108  	t[5], c = bits.Sub64(r[5], p[5], c)
   109  	t[6], c = bits.Sub64(r[6], p[6], c)
   110  	t[7], c = bits.Sub64(r[7], p[7], c)
   111  
   112  	w := 0 - c
   113  	r[0] = ctPick64(w, r[0], t[0])
   114  	r[1] = ctPick64(w, r[1], t[1])
   115  	r[2] = ctPick64(w, r[2], t[2])
   116  	r[3] = ctPick64(w, r[3], t[3])
   117  	r[4] = ctPick64(w, r[4], t[4])
   118  	r[5] = ctPick64(w, r[5], t[5])
   119  	r[6] = ctPick64(w, r[6], t[6])
   120  	r[7] = ctPick64(w, r[7], t[7])
   121  }
   122  
   123  func mulGeneric(r, x, y *fp) {
   124  	var s fp // keeps intermediate results
   125  	var t1, t2 [9]uint64
   126  	var c, q uint64
   127  
   128  	for i := 0; i < numWords-1; i++ {
   129  		q = ((x[i] * y[0]) + s[0]) * pNegInv[0]
   130  		mul576Generic(&t1, &p, q)
   131  		mul576Generic(&t2, y, x[i])
   132  
   133  		// x[i]*y + q_i*p
   134  		t1[0], c = bits.Add64(t1[0], t2[0], 0)
   135  		t1[1], c = bits.Add64(t1[1], t2[1], c)
   136  		t1[2], c = bits.Add64(t1[2], t2[2], c)
   137  		t1[3], c = bits.Add64(t1[3], t2[3], c)
   138  		t1[4], c = bits.Add64(t1[4], t2[4], c)
   139  		t1[5], c = bits.Add64(t1[5], t2[5], c)
   140  		t1[6], c = bits.Add64(t1[6], t2[6], c)
   141  		t1[7], c = bits.Add64(t1[7], t2[7], c)
   142  		t1[8], _ = bits.Add64(t1[8], t2[8], c)
   143  
   144  		// s = (s + x[i]*y + q_i * p) / R
   145  		_, c = bits.Add64(t1[0], s[0], 0)
   146  		s[0], c = bits.Add64(t1[1], s[1], c)
   147  		s[1], c = bits.Add64(t1[2], s[2], c)
   148  		s[2], c = bits.Add64(t1[3], s[3], c)
   149  		s[3], c = bits.Add64(t1[4], s[4], c)
   150  		s[4], c = bits.Add64(t1[5], s[5], c)
   151  		s[5], c = bits.Add64(t1[6], s[6], c)
   152  		s[6], c = bits.Add64(t1[7], s[7], c)
   153  		s[7], _ = bits.Add64(t1[8], 0, c)
   154  	}
   155  
   156  	// last iteration stores result in r
   157  	q = ((x[numWords-1] * y[0]) + s[0]) * pNegInv[0]
   158  	mul576Generic(&t1, &p, q)
   159  	mul576Generic(&t2, y, x[numWords-1])
   160  
   161  	t1[0], c = bits.Add64(t1[0], t2[0], c)
   162  	t1[1], c = bits.Add64(t1[1], t2[1], c)
   163  	t1[2], c = bits.Add64(t1[2], t2[2], c)
   164  	t1[3], c = bits.Add64(t1[3], t2[3], c)
   165  	t1[4], c = bits.Add64(t1[4], t2[4], c)
   166  	t1[5], c = bits.Add64(t1[5], t2[5], c)
   167  	t1[6], c = bits.Add64(t1[6], t2[6], c)
   168  	t1[7], c = bits.Add64(t1[7], t2[7], c)
   169  	t1[8], _ = bits.Add64(t1[8], t2[8], c)
   170  
   171  	_, c = bits.Add64(t1[0], s[0], 0)
   172  	r[0], c = bits.Add64(t1[1], s[1], c)
   173  	r[1], c = bits.Add64(t1[2], s[2], c)
   174  	r[2], c = bits.Add64(t1[3], s[3], c)
   175  	r[3], c = bits.Add64(t1[4], s[4], c)
   176  	r[4], c = bits.Add64(t1[5], s[5], c)
   177  	r[5], c = bits.Add64(t1[6], s[6], c)
   178  	r[6], c = bits.Add64(t1[7], s[7], c)
   179  	r[7], _ = bits.Add64(t1[8], 0, c)
   180  }