github.com/consensys/gnark-crypto@v0.14.0/ecc/secp256k1/fp/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 fp 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 55834587549, 37 0, 38 0, 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 }