Nie możesz wybrać więcej, niż 25 tematów Tematy muszą się zaczynać od litery lub cyfry, mogą zawierać myślniki ('-') i mogą mieć do 35 znaków.
 
 
 

198 wiersze
4.1 KiB

  1. // +build noasm !amd64
  2. package p503
  3. import (
  4. . "github.com/cloudflare/p751sidh/internal/arith"
  5. . "github.com/cloudflare/p751sidh/internal/isogeny"
  6. )
  7. // Compute z = x + y (mod p).
  8. func fp503AddReduced(z, x, y *FpElement) {
  9. var carry uint64
  10. // z=x+y % p503
  11. for i := 0; i < NumWords; i++ {
  12. z[i], carry = Addc64(carry, x[i], y[i])
  13. }
  14. // z = z - p503x2
  15. carry = 0
  16. for i := 0; i < NumWords; i++ {
  17. z[i], carry = Subc64(carry, z[i], p503x2[i])
  18. }
  19. // if z<0 add p503x2 back
  20. mask := uint64(0 - carry)
  21. carry = 0
  22. for i := 0; i < NumWords; i++ {
  23. z[i], carry = Addc64(carry, z[i], p503x2[i]&mask)
  24. }
  25. }
  26. // Compute z = x - y (mod p).
  27. func fp503SubReduced(z, x, y *FpElement) {
  28. var borrow uint64
  29. // z = z - p503x2
  30. for i := 0; i < NumWords; i++ {
  31. z[i], borrow = Subc64(borrow, x[i], y[i])
  32. }
  33. // if z<0 add p503x2 back
  34. mask := uint64(0 - borrow)
  35. borrow = 0
  36. for i := 0; i < NumWords; i++ {
  37. z[i], borrow = Addc64(borrow, z[i], p503x2[i]&mask)
  38. }
  39. }
  40. // Conditionally swaps bits in x and y in constant time.
  41. // mask indicates bits to be swapped (set bits are swapped)
  42. // For details see "Hackers Delight, 2.20"
  43. //
  44. // Implementation doesn't actually depend on a prime field.
  45. func fp503ConditionalSwap(x, y *FpElement, mask uint8) {
  46. var tmp, mask64 uint64
  47. mask64 = 0 - uint64(mask)
  48. for i := 0; i < NumWords; i++ {
  49. tmp = mask64 & (x[i] ^ y[i])
  50. x[i] = tmp ^ x[i]
  51. y[i] = tmp ^ y[i]
  52. }
  53. }
  54. // Perform Montgomery reduction: set z = x R^{-1} (mod 2*p)
  55. // with R=2^512. Destroys the input value.
  56. func fp503MontgomeryReduce(z *FpElement, x *FpElementX2) {
  57. var carry, t, u, v uint64
  58. var uv Uint128
  59. var count int
  60. count = 3 // number of 0 digits in the least significat part of p503 + 1
  61. for i := 0; i < NumWords; i++ {
  62. for j := 0; j < i; j++ {
  63. if j < (i - count + 1) {
  64. uv = Mul64(z[j], p503p1[i-j])
  65. v, carry = Addc64(0, uv.L, v)
  66. u, carry = Addc64(carry, uv.H, u)
  67. t += carry
  68. }
  69. }
  70. v, carry = Addc64(0, v, x[i])
  71. u, carry = Addc64(carry, u, 0)
  72. t += carry
  73. z[i] = v
  74. v = u
  75. u = t
  76. t = 0
  77. }
  78. for i := NumWords; i < 2*NumWords-1; i++ {
  79. if count > 0 {
  80. count--
  81. }
  82. for j := i - NumWords + 1; j < NumWords; j++ {
  83. if j < (NumWords - count) {
  84. uv = Mul64(z[j], p503p1[i-j])
  85. v, carry = Addc64(0, uv.L, v)
  86. u, carry = Addc64(carry, uv.H, u)
  87. t += carry
  88. }
  89. }
  90. v, carry = Addc64(0, v, x[i])
  91. u, carry = Addc64(carry, u, 0)
  92. t += carry
  93. z[i-NumWords] = v
  94. v = u
  95. u = t
  96. t = 0
  97. }
  98. v, carry = Addc64(0, v, x[2*NumWords-1])
  99. z[NumWords-1] = v
  100. }
  101. // Compute z = x * y.
  102. func fp503Mul(z *FpElementX2, x, y *FpElement) {
  103. var u, v, t uint64
  104. var carry uint64
  105. var uv Uint128
  106. for i := uint64(0); i < NumWords; i++ {
  107. for j := uint64(0); j <= i; j++ {
  108. uv = Mul64(x[j], y[i-j])
  109. v, carry = Addc64(0, uv.L, v)
  110. u, carry = Addc64(carry, uv.H, u)
  111. t += carry
  112. }
  113. z[i] = v
  114. v = u
  115. u = t
  116. t = 0
  117. }
  118. for i := NumWords; i < (2*NumWords)-1; i++ {
  119. for j := i - NumWords + 1; j < NumWords; j++ {
  120. uv = Mul64(x[j], y[i-j])
  121. v, carry = Addc64(0, uv.L, v)
  122. u, carry = Addc64(carry, uv.H, u)
  123. t += carry
  124. }
  125. z[i] = v
  126. v = u
  127. u = t
  128. t = 0
  129. }
  130. z[2*NumWords-1] = v
  131. }
  132. // Compute z = x + y, without reducing mod p.
  133. func fp503AddLazy(z, x, y *FpElement) {
  134. var carry uint64
  135. for i := 0; i < NumWords; i++ {
  136. z[i], carry = Addc64(carry, x[i], y[i])
  137. }
  138. }
  139. // Compute z = x + y, without reducing mod p.
  140. func fp503X2AddLazy(z, x, y *FpElementX2) {
  141. var carry uint64
  142. for i := 0; i < 2*NumWords; i++ {
  143. z[i], carry = Addc64(carry, x[i], y[i])
  144. }
  145. }
  146. // Reduce a field element in [0, 2*p) to one in [0,p).
  147. func fp503StrongReduce(x *FpElement) {
  148. var borrow, mask uint64
  149. for i := 0; i < NumWords; i++ {
  150. x[i], borrow = Subc64(borrow, x[i], p503[i])
  151. }
  152. // Sets all bits if borrow = 1
  153. mask = 0 - borrow
  154. borrow = 0
  155. for i := 0; i < NumWords; i++ {
  156. x[i], borrow = Addc64(borrow, x[i], p503[i]&mask)
  157. }
  158. }
  159. // Compute z = x - y, without reducing mod p.
  160. func fp503X2SubLazy(z, x, y *FpElementX2) {
  161. var borrow, mask uint64
  162. for i := 0; i < 2*NumWords; i++ {
  163. z[i], borrow = Subc64(borrow, x[i], y[i])
  164. }
  165. // Sets all bits if borrow = 1
  166. mask = 0 - borrow
  167. borrow = 0
  168. for i := NumWords; i < 2*NumWords; i++ {
  169. z[i], borrow = Addc64(borrow, z[i], p503[i-NumWords]&mask)
  170. }
  171. }