github.com/cloudflare/circl@v1.5.0/dh/sidh/internal/p503/arith_generic.go (about)

     1  // Code generated by go generate; DO NOT EDIT.
     2  // This file was generated by robots.
     3  
     4  //go:build purego || (!amd64 && !arm64)
     5  // +build purego !amd64,!arm64
     6  
     7  package p503
     8  
     9  import (
    10  	"math/bits"
    11  
    12  	"github.com/cloudflare/circl/dh/sidh/internal/common"
    13  )
    14  
    15  // Compute z = x + y (mod p).
    16  func addP503(z, x, y *common.Fp) {
    17  	var carry uint64
    18  
    19  	// z=x+y % P503
    20  	for i := 0; i < FpWords; i++ {
    21  		z[i], carry = bits.Add64(x[i], y[i], carry)
    22  	}
    23  
    24  	// z = z - P503x2
    25  	carry = 0
    26  	for i := 0; i < FpWords; i++ {
    27  		z[i], carry = bits.Sub64(z[i], P503x2[i], carry)
    28  	}
    29  
    30  	// if z<0 add P503x2 back
    31  	mask := uint64(0 - carry)
    32  	carry = 0
    33  	for i := 0; i < FpWords; i++ {
    34  		z[i], carry = bits.Add64(z[i], P503x2[i]&mask, carry)
    35  	}
    36  }
    37  
    38  // Compute z = x - y (mod p).
    39  func subP503(z, x, y *common.Fp) {
    40  	var borrow uint64
    41  
    42  	for i := 0; i < FpWords; i++ {
    43  		z[i], borrow = bits.Sub64(x[i], y[i], borrow)
    44  	}
    45  
    46  	mask := uint64(0 - borrow)
    47  	borrow = 0
    48  
    49  	for i := 0; i < FpWords; i++ {
    50  		z[i], borrow = bits.Add64(z[i], P503x2[i]&mask, borrow)
    51  	}
    52  }
    53  
    54  // If choice = 0, leave x unchanged. If choice = 1, sets x to y.
    55  // If choice is neither 0 nor 1 then behaviour is undefined.
    56  // This function executes in constant time.
    57  func cmovP503(x, y *common.Fp, choice uint8) {
    58  	mask := 0 - uint64(choice)
    59  	for i := 0; i < FpWords; i++ {
    60  		x[i] ^= mask & (x[i] ^ y[i])
    61  	}
    62  }
    63  
    64  // Conditionally swaps bits in x and y in constant time.
    65  // mask indicates bits to be swapped (set bits are swapped)
    66  // For details see "Hackers Delight, 2.20"
    67  //
    68  // Implementation doesn't actually depend on a prime field.
    69  func cswapP503(x, y *common.Fp, mask uint8) {
    70  	var tmp, mask64 uint64
    71  
    72  	mask64 = 0 - uint64(mask)
    73  	for i := 0; i < FpWords; i++ {
    74  		tmp = mask64 & (x[i] ^ y[i])
    75  		x[i] = tmp ^ x[i]
    76  		y[i] = tmp ^ y[i]
    77  	}
    78  }
    79  
    80  // Perform Montgomery reduction: set z = x R^{-1} (mod 2*p)
    81  // with R=2^(FpWords*64). Destroys the input value.
    82  func rdcP503(z *common.Fp, x *common.FpX2) {
    83  	var carry, t, u, v uint64
    84  	var hi, lo uint64
    85  	var count int
    86  
    87  	count = P503p1Zeros
    88  
    89  	for i := 0; i < FpWords; i++ {
    90  		for j := 0; j < i; j++ {
    91  			if j < (i - count + 1) {
    92  				hi, lo = bits.Mul64(z[j], P503p1[i-j])
    93  				v, carry = bits.Add64(lo, v, 0)
    94  				u, carry = bits.Add64(hi, u, carry)
    95  				t += carry
    96  			}
    97  		}
    98  		v, carry = bits.Add64(v, x[i], 0)
    99  		u, carry = bits.Add64(u, 0, carry)
   100  		t += carry
   101  
   102  		z[i] = v
   103  		v = u
   104  		u = t
   105  		t = 0
   106  	}
   107  
   108  	for i := FpWords; i < 2*FpWords-1; i++ {
   109  		if count > 0 {
   110  			count--
   111  		}
   112  		for j := i - FpWords + 1; j < FpWords; j++ {
   113  			if j < (FpWords - count) {
   114  				hi, lo = bits.Mul64(z[j], P503p1[i-j])
   115  				v, carry = bits.Add64(lo, v, 0)
   116  				u, carry = bits.Add64(hi, u, carry)
   117  				t += carry
   118  			}
   119  		}
   120  		v, carry = bits.Add64(v, x[i], 0)
   121  		u, carry = bits.Add64(u, 0, carry)
   122  
   123  		t += carry
   124  		z[i-FpWords] = v
   125  		v = u
   126  		u = t
   127  		t = 0
   128  	}
   129  	v, _ = bits.Add64(v, x[2*FpWords-1], 0)
   130  	z[FpWords-1] = v
   131  }
   132  
   133  // Compute z = x * y.
   134  func mulP503(z *common.FpX2, x, y *common.Fp) {
   135  	var u, v, t uint64
   136  	var hi, lo uint64
   137  	var carry uint64
   138  
   139  	for i := uint64(0); i < FpWords; i++ {
   140  		for j := uint64(0); j <= i; j++ {
   141  			hi, lo = bits.Mul64(x[j], y[i-j])
   142  			v, carry = bits.Add64(lo, v, 0)
   143  			u, carry = bits.Add64(hi, u, carry)
   144  			t += carry
   145  		}
   146  		z[i] = v
   147  		v = u
   148  		u = t
   149  		t = 0
   150  	}
   151  
   152  	for i := FpWords; i < (2*FpWords)-1; i++ {
   153  		for j := i - FpWords + 1; j < FpWords; j++ {
   154  			hi, lo = bits.Mul64(x[j], y[i-j])
   155  			v, carry = bits.Add64(lo, v, 0)
   156  			u, carry = bits.Add64(hi, u, carry)
   157  			t += carry
   158  		}
   159  		z[i] = v
   160  		v = u
   161  		u = t
   162  		t = 0
   163  	}
   164  	z[2*FpWords-1] = v
   165  }
   166  
   167  // Compute z = x + y, without reducing mod p.
   168  func adlP503(z, x, y *common.FpX2) {
   169  	var carry uint64
   170  	for i := 0; i < 2*FpWords; i++ {
   171  		z[i], carry = bits.Add64(x[i], y[i], carry)
   172  	}
   173  }
   174  
   175  // Reduce a field element in [0, 2*p) to one in [0,p).
   176  func modP503(x *common.Fp) {
   177  	var borrow, mask uint64
   178  	for i := 0; i < FpWords; i++ {
   179  		x[i], borrow = bits.Sub64(x[i], P503[i], borrow)
   180  	}
   181  
   182  	// Sets all bits if borrow = 1
   183  	mask = 0 - borrow
   184  	borrow = 0
   185  	for i := 0; i < FpWords; i++ {
   186  		x[i], borrow = bits.Add64(x[i], P503[i]&mask, borrow)
   187  	}
   188  }
   189  
   190  // Compute z = x - y, without reducing mod p.
   191  func sulP503(z, x, y *common.FpX2) {
   192  	var borrow, mask uint64
   193  	for i := 0; i < 2*FpWords; i++ {
   194  		z[i], borrow = bits.Sub64(x[i], y[i], borrow)
   195  	}
   196  
   197  	// Sets all bits if borrow = 1
   198  	mask = 0 - borrow
   199  	borrow = 0
   200  	for i := FpWords; i < 2*FpWords; i++ {
   201  		z[i], borrow = bits.Add64(z[i], P503[i-FpWords]&mask, borrow)
   202  	}
   203  }