// Copyright 2020 ConsenSys Software Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // Code generated by consensys/gnark-crypto DO NOT EDIT package ff import ( "crypto/rand" "encoding/binary" "errors" "io" "math/big" "math/bits" "reflect" "strconv" "sync" ) // Element represents a field element stored on 4 words (uint64) // Element are assumed to be in Montgomery form in all methods // field modulus q = // // 21888242871839275222246405745257275088548364400416034343698204186575808495617 type Element [4]uint64 // Limbs number of 64 bits words needed to represent Element const Limbs = 4 // Bits number bits needed to represent Element const Bits = 254 // Bytes number bytes needed to represent Element const Bytes = Limbs * 8 // field modulus stored as big.Int var _modulus big.Int // Modulus returns q as a big.Int // q = // // 21888242871839275222246405745257275088548364400416034343698204186575808495617 func Modulus() *big.Int { return new(big.Int).Set(&_modulus) } // q (modulus) var qElement = Element{ 4891460686036598785, 2896914383306846353, 13281191951274694749, 3486998266802970665, } // rSquare var rSquare = Element{ 1997599621687373223, 6052339484930628067, 10108755138030829701, 150537098327114917, } var bigIntPool = sync.Pool{ New: func() interface{} { return new(big.Int) }, } func init() { _modulus.SetString("21888242871839275222246405745257275088548364400416034343698204186575808495617", 10) } // NewElement returns a new Element func NewElement() *Element { return &Element{} } // NewElementFromUint64 returns a new Element from a uint64 value // // it is equivalent to // var v NewElement // v.SetUint64(...) func NewElementFromUint64(v uint64) Element { z := Element{v} z.Mul(&z, &rSquare) return z } // SetUint64 z = v, sets z LSB to v (non-Montgomery form) and convert z to Montgomery form func (z *Element) SetUint64(v uint64) *Element { *z = Element{v} return z.Mul(z, &rSquare) // z.ToMont() } // Set z = x func (z *Element) Set(x *Element) *Element { z[0] = x[0] z[1] = x[1] z[2] = x[2] z[3] = x[3] return z } // SetInterface converts provided interface into Element // returns an error if provided type is not supported // supported types: Element, *Element, uint64, int, string (interpreted as base10 integer), // *big.Int, big.Int, []byte func (z *Element) SetInterface(i1 interface{}) (*Element, error) { switch c1 := i1.(type) { case Element: return z.Set(&c1), nil case *Element: return z.Set(c1), nil case uint64: return z.SetUint64(c1), nil case int: return z.SetString(strconv.Itoa(c1)), nil case string: return z.SetString(c1), nil case *big.Int: return z.SetBigInt(c1), nil case big.Int: return z.SetBigInt(&c1), nil case []byte: return z.SetBytes(c1), nil default: return nil, errors.New("can't set ff.Element from type " + reflect.TypeOf(i1).String()) } } // SetZero z = 0 func (z *Element) SetZero() *Element { z[0] = 0 z[1] = 0 z[2] = 0 z[3] = 0 return z } // SetOne z = 1 (in Montgomery form) func (z *Element) SetOne() *Element { z[0] = 12436184717236109307 z[1] = 3962172157175319849 z[2] = 7381016538464732718 z[3] = 1011752739694698287 return z } // Div z = x*y^-1 mod q func (z *Element) Div(x, y *Element) *Element { var yInv Element yInv.Inverse(y) z.Mul(x, &yInv) return z } // Bit returns the i'th bit, with lsb == bit 0. // It is the responsability of the caller to convert from Montgomery to Regular form if needed func (z *Element) Bit(i uint64) uint64 { j := i / 64 if j >= 4 { return 0 } return uint64(z[j] >> (i % 64) & 1) } // Equal returns z == x func (z *Element) Equal(x *Element) bool { return (z[3] == x[3]) && (z[2] == x[2]) && (z[1] == x[1]) && (z[0] == x[0]) } // IsZero returns z == 0 func (z *Element) IsZero() bool { return (z[3] | z[2] | z[1] | z[0]) == 0 } // IsUint64 returns true if z[0] >= 0 and all other words are 0 func (z *Element) IsUint64() bool { return (z[3] | z[2] | z[1]) == 0 } // Cmp compares (lexicographic order) z and x and returns: // // -1 if z < x // 0 if z == x // +1 if z > x // func (z *Element) Cmp(x *Element) int { _z := *z _x := *x _z.FromMont() _x.FromMont() if _z[3] > _x[3] { return 1 } else if _z[3] < _x[3] { return -1 } if _z[2] > _x[2] { return 1 } else if _z[2] < _x[2] { return -1 } if _z[1] > _x[1] { return 1 } else if _z[1] < _x[1] { return -1 } if _z[0] > _x[0] { return 1 } else if _z[0] < _x[0] { return -1 } return 0 } // LexicographicallyLargest returns true if this element is strictly lexicographically // larger than its negation, false otherwise func (z *Element) LexicographicallyLargest() bool { // adapted from github.com/zkcrypto/bls12_381 // we check if the element is larger than (q-1) / 2 // if z - (((q -1) / 2) + 1) have no underflow, then z > (q-1) / 2 _z := *z _z.FromMont() var b uint64 _, b = bits.Sub64(_z[0], 11669102379873075201, 0) _, b = bits.Sub64(_z[1], 10671829228508198984, b) _, b = bits.Sub64(_z[2], 15863968012492123182, b) _, b = bits.Sub64(_z[3], 1743499133401485332, b) return b == 0 } // SetRandom sets z to a random element < q func (z *Element) SetRandom() (*Element, error) { var bytes [32]byte if _, err := io.ReadFull(rand.Reader, bytes[:]); err != nil { return nil, err } z[0] = binary.BigEndian.Uint64(bytes[0:8]) z[1] = binary.BigEndian.Uint64(bytes[8:16]) z[2] = binary.BigEndian.Uint64(bytes[16:24]) z[3] = binary.BigEndian.Uint64(bytes[24:32]) z[3] %= 3486998266802970665 // if z > q --> z -= q // note: this is NOT constant time if !(z[3] < 3486998266802970665 || (z[3] == 3486998266802970665 && (z[2] < 13281191951274694749 || (z[2] == 13281191951274694749 && (z[1] < 2896914383306846353 || (z[1] == 2896914383306846353 && (z[0] < 4891460686036598785))))))) { var b uint64 z[0], b = bits.Sub64(z[0], 4891460686036598785, 0) z[1], b = bits.Sub64(z[1], 2896914383306846353, b) z[2], b = bits.Sub64(z[2], 13281191951274694749, b) z[3], _ = bits.Sub64(z[3], 3486998266802970665, b) } return z, nil } // One returns 1 (in montgommery form) func One() Element { var one Element one.SetOne() return one } // Halve sets z to z / 2 (mod p) func (z *Element) Halve() { if z[0]&1 == 1 { var carry uint64 // z = z + q z[0], carry = bits.Add64(z[0], 4891460686036598785, 0) z[1], carry = bits.Add64(z[1], 2896914383306846353, carry) z[2], carry = bits.Add64(z[2], 13281191951274694749, carry) z[3], _ = bits.Add64(z[3], 3486998266802970665, carry) } // z = z >> 1 z[0] = z[0]>>1 | z[1]<<63 z[1] = z[1]>>1 | z[2]<<63 z[2] = z[2]>>1 | z[3]<<63 z[3] >>= 1 } // API with assembly impl // Mul z = x * y mod q // see https://hackmd.io/@zkteam/modular_multiplication func (z *Element) Mul(x, y *Element) *Element { mul(z, x, y) return z } // Square z = x * x mod q // see https://hackmd.io/@zkteam/modular_multiplication func (z *Element) Square(x *Element) *Element { mul(z, x, x) return z } // FromMont converts z in place (i.e. mutates) from Montgomery to regular representation // sets and returns z = z * 1 func (z *Element) FromMont() *Element { fromMont(z) return z } // Add z = x + y mod q func (z *Element) Add(x, y *Element) *Element { add(z, x, y) return z } // Double z = x + x mod q, aka Lsh 1 func (z *Element) Double(x *Element) *Element { double(z, x) return z } // Sub z = x - y mod q func (z *Element) Sub(x, y *Element) *Element { sub(z, x, y) return z } // Neg z = q - x func (z *Element) Neg(x *Element) *Element { neg(z, x) return z } // Generic (no ADX instructions, no AMD64) versions of multiplication and squaring algorithms func _mulGeneric(z, x, y *Element) { var t [4]uint64 var c [3]uint64 { // round 0 v := x[0] c[1], c[0] = bits.Mul64(v, y[0]) m := c[0] * 14042775128853446655 c[2] = madd0(m, 4891460686036598785, c[0]) c[1], c[0] = madd1(v, y[1], c[1]) c[2], t[0] = madd2(m, 2896914383306846353, c[2], c[0]) c[1], c[0] = madd1(v, y[2], c[1]) c[2], t[1] = madd2(m, 13281191951274694749, c[2], c[0]) c[1], c[0] = madd1(v, y[3], c[1]) t[3], t[2] = madd3(m, 3486998266802970665, c[0], c[2], c[1]) } { // round 1 v := x[1] c[1], c[0] = madd1(v, y[0], t[0]) m := c[0] * 14042775128853446655 c[2] = madd0(m, 4891460686036598785, c[0]) c[1], c[0] = madd2(v, y[1], c[1], t[1]) c[2], t[0] = madd2(m, 2896914383306846353, c[2], c[0]) c[1], c[0] = madd2(v, y[2], c[1], t[2]) c[2], t[1] = madd2(m, 13281191951274694749, c[2], c[0]) c[1], c[0] = madd2(v, y[3], c[1], t[3]) t[3], t[2] = madd3(m, 3486998266802970665, c[0], c[2], c[1]) } { // round 2 v := x[2] c[1], c[0] = madd1(v, y[0], t[0]) m := c[0] * 14042775128853446655 c[2] = madd0(m, 4891460686036598785, c[0]) c[1], c[0] = madd2(v, y[1], c[1], t[1]) c[2], t[0] = madd2(m, 2896914383306846353, c[2], c[0]) c[1], c[0] = madd2(v, y[2], c[1], t[2]) c[2], t[1] = madd2(m, 13281191951274694749, c[2], c[0]) c[1], c[0] = madd2(v, y[3], c[1], t[3]) t[3], t[2] = madd3(m, 3486998266802970665, c[0], c[2], c[1]) } { // round 3 v := x[3] c[1], c[0] = madd1(v, y[0], t[0]) m := c[0] * 14042775128853446655 c[2] = madd0(m, 4891460686036598785, c[0]) c[1], c[0] = madd2(v, y[1], c[1], t[1]) c[2], z[0] = madd2(m, 2896914383306846353, c[2], c[0]) c[1], c[0] = madd2(v, y[2], c[1], t[2]) c[2], z[1] = madd2(m, 13281191951274694749, c[2], c[0]) c[1], c[0] = madd2(v, y[3], c[1], t[3]) z[3], z[2] = madd3(m, 3486998266802970665, c[0], c[2], c[1]) } // if z > q --> z -= q // note: this is NOT constant time if !(z[3] < 3486998266802970665 || (z[3] == 3486998266802970665 && (z[2] < 13281191951274694749 || (z[2] == 13281191951274694749 && (z[1] < 2896914383306846353 || (z[1] == 2896914383306846353 && (z[0] < 4891460686036598785))))))) { var b uint64 z[0], b = bits.Sub64(z[0], 4891460686036598785, 0) z[1], b = bits.Sub64(z[1], 2896914383306846353, b) z[2], b = bits.Sub64(z[2], 13281191951274694749, b) z[3], _ = bits.Sub64(z[3], 3486998266802970665, b) } } func _fromMontGeneric(z *Element) { // the following lines implement z = z * 1 // with a modified CIOS montgomery multiplication { // m = z[0]n'[0] mod W m := z[0] * 14042775128853446655 C := madd0(m, 4891460686036598785, z[0]) C, z[0] = madd2(m, 2896914383306846353, z[1], C) C, z[1] = madd2(m, 13281191951274694749, z[2], C) C, z[2] = madd2(m, 3486998266802970665, z[3], C) z[3] = C } { // m = z[0]n'[0] mod W m := z[0] * 14042775128853446655 C := madd0(m, 4891460686036598785, z[0]) C, z[0] = madd2(m, 2896914383306846353, z[1], C) C, z[1] = madd2(m, 13281191951274694749, z[2], C) C, z[2] = madd2(m, 3486998266802970665, z[3], C) z[3] = C } { // m = z[0]n'[0] mod W m := z[0] * 14042775128853446655 C := madd0(m, 4891460686036598785, z[0]) C, z[0] = madd2(m, 2896914383306846353, z[1], C) C, z[1] = madd2(m, 13281191951274694749, z[2], C) C, z[2] = madd2(m, 3486998266802970665, z[3], C) z[3] = C } { // m = z[0]n'[0] mod W m := z[0] * 14042775128853446655 C := madd0(m, 4891460686036598785, z[0]) C, z[0] = madd2(m, 2896914383306846353, z[1], C) C, z[1] = madd2(m, 13281191951274694749, z[2], C) C, z[2] = madd2(m, 3486998266802970665, z[3], C) z[3] = C } // if z > q --> z -= q // note: this is NOT constant time if !(z[3] < 3486998266802970665 || (z[3] == 3486998266802970665 && (z[2] < 13281191951274694749 || (z[2] == 13281191951274694749 && (z[1] < 2896914383306846353 || (z[1] == 2896914383306846353 && (z[0] < 4891460686036598785))))))) { var b uint64 z[0], b = bits.Sub64(z[0], 4891460686036598785, 0) z[1], b = bits.Sub64(z[1], 2896914383306846353, b) z[2], b = bits.Sub64(z[2], 13281191951274694749, b) z[3], _ = bits.Sub64(z[3], 3486998266802970665, b) } } func _addGeneric(z, x, y *Element) { var carry uint64 z[0], carry = bits.Add64(x[0], y[0], 0) z[1], carry = bits.Add64(x[1], y[1], carry) z[2], carry = bits.Add64(x[2], y[2], carry) z[3], _ = bits.Add64(x[3], y[3], carry) // if z > q --> z -= q // note: this is NOT constant time if !(z[3] < 3486998266802970665 || (z[3] == 3486998266802970665 && (z[2] < 13281191951274694749 || (z[2] == 13281191951274694749 && (z[1] < 2896914383306846353 || (z[1] == 2896914383306846353 && (z[0] < 4891460686036598785))))))) { var b uint64 z[0], b = bits.Sub64(z[0], 4891460686036598785, 0) z[1], b = bits.Sub64(z[1], 2896914383306846353, b) z[2], b = bits.Sub64(z[2], 13281191951274694749, b) z[3], _ = bits.Sub64(z[3], 3486998266802970665, b) } } func _doubleGeneric(z, x *Element) { var carry uint64 z[0], carry = bits.Add64(x[0], x[0], 0) z[1], carry = bits.Add64(x[1], x[1], carry) z[2], carry = bits.Add64(x[2], x[2], carry) z[3], _ = bits.Add64(x[3], x[3], carry) // if z > q --> z -= q // note: this is NOT constant time if !(z[3] < 3486998266802970665 || (z[3] == 3486998266802970665 && (z[2] < 13281191951274694749 || (z[2] == 13281191951274694749 && (z[1] < 2896914383306846353 || (z[1] == 2896914383306846353 && (z[0] < 4891460686036598785))))))) { var b uint64 z[0], b = bits.Sub64(z[0], 4891460686036598785, 0) z[1], b = bits.Sub64(z[1], 2896914383306846353, b) z[2], b = bits.Sub64(z[2], 13281191951274694749, b) z[3], _ = bits.Sub64(z[3], 3486998266802970665, b) } } func _subGeneric(z, x, y *Element) { var b uint64 z[0], b = bits.Sub64(x[0], y[0], 0) z[1], b = bits.Sub64(x[1], y[1], b) z[2], b = bits.Sub64(x[2], y[2], b) z[3], b = bits.Sub64(x[3], y[3], b) if b != 0 { var c uint64 z[0], c = bits.Add64(z[0], 4891460686036598785, 0) z[1], c = bits.Add64(z[1], 2896914383306846353, c) z[2], c = bits.Add64(z[2], 13281191951274694749, c) z[3], _ = bits.Add64(z[3], 3486998266802970665, c) } } func _negGeneric(z, x *Element) { if x.IsZero() { z.SetZero() return } var borrow uint64 z[0], borrow = bits.Sub64(4891460686036598785, x[0], 0) z[1], borrow = bits.Sub64(2896914383306846353, x[1], borrow) z[2], borrow = bits.Sub64(13281191951274694749, x[2], borrow) z[3], _ = bits.Sub64(3486998266802970665, x[3], borrow) } func _reduceGeneric(z *Element) { // if z > q --> z -= q // note: this is NOT constant time if !(z[3] < 3486998266802970665 || (z[3] == 3486998266802970665 && (z[2] < 13281191951274694749 || (z[2] == 13281191951274694749 && (z[1] < 2896914383306846353 || (z[1] == 2896914383306846353 && (z[0] < 4891460686036598785))))))) { var b uint64 z[0], b = bits.Sub64(z[0], 4891460686036598785, 0) z[1], b = bits.Sub64(z[1], 2896914383306846353, b) z[2], b = bits.Sub64(z[2], 13281191951274694749, b) z[3], _ = bits.Sub64(z[3], 3486998266802970665, b) } } func mulByConstant(z *Element, c uint8) { switch c { case 0: z.SetZero() return case 1: return case 2: z.Double(z) return case 3: _z := *z z.Double(z).Add(z, &_z) case 5: _z := *z z.Double(z).Double(z).Add(z, &_z) default: var y Element y.SetUint64(uint64(c)) z.Mul(z, &y) } } // BatchInvert returns a new slice with every element inverted. // Uses Montgomery batch inversion trick func BatchInvert(a []Element) []Element { res := make([]Element, len(a)) if len(a) == 0 { return res } zeroes := make([]bool, len(a)) accumulator := One() for i := 0; i < len(a); i++ { if a[i].IsZero() { zeroes[i] = true continue } res[i] = accumulator accumulator.Mul(&accumulator, &a[i]) } accumulator.Inverse(&accumulator) for i := len(a) - 1; i >= 0; i-- { if zeroes[i] { continue } res[i].Mul(&res[i], &accumulator) accumulator.Mul(&accumulator, &a[i]) } return res } func _butterflyGeneric(a, b *Element) { t := *a a.Add(a, b) b.Sub(&t, b) } // BitLen returns the minimum number of bits needed to represent z // returns 0 if z == 0 func (z *Element) BitLen() int { if z[3] != 0 { return 192 + bits.Len64(z[3]) } if z[2] != 0 { return 128 + bits.Len64(z[2]) } if z[1] != 0 { return 64 + bits.Len64(z[1]) } return bits.Len64(z[0]) } // Exp z = x^exponent mod q func (z *Element) Exp(x Element, exponent *big.Int) *Element { var bZero big.Int if exponent.Cmp(&bZero) == 0 { return z.SetOne() } z.Set(&x) for i := exponent.BitLen() - 2; i >= 0; i-- { z.Square(z) if exponent.Bit(i) == 1 { z.Mul(z, &x) } } return z } // ToMont converts z to Montgomery form // sets and returns z = z * r^2 func (z *Element) ToMont() *Element { return z.Mul(z, &rSquare) } // ToRegular returns z in regular form (doesn't mutate z) func (z Element) ToRegular() Element { return *z.FromMont() } // String returns the string form of an Element in Montgomery form func (z *Element) String() string { zz := *z zz.FromMont() if zz.IsUint64() { return strconv.FormatUint(zz[0], 10) } else { var zzNeg Element zzNeg.Neg(z) zzNeg.FromMont() if zzNeg.IsUint64() { return "-" + strconv.FormatUint(zzNeg[0], 10) } } vv := bigIntPool.Get().(*big.Int) defer bigIntPool.Put(vv) return zz.ToBigInt(vv).String() } // ToBigInt returns z as a big.Int in Montgomery form func (z *Element) ToBigInt(res *big.Int) *big.Int { var b [Limbs * 8]byte binary.BigEndian.PutUint64(b[24:32], z[0]) binary.BigEndian.PutUint64(b[16:24], z[1]) binary.BigEndian.PutUint64(b[8:16], z[2]) binary.BigEndian.PutUint64(b[0:8], z[3]) return res.SetBytes(b[:]) } // ToBigIntRegular returns z as a big.Int in regular form func (z Element) ToBigIntRegular(res *big.Int) *big.Int { z.FromMont() return z.ToBigInt(res) } // Bytes returns the regular (non montgomery) value // of z as a big-endian byte array. func (z *Element) Bytes() (res [Limbs * 8]byte) { _z := z.ToRegular() binary.BigEndian.PutUint64(res[24:32], _z[0]) binary.BigEndian.PutUint64(res[16:24], _z[1]) binary.BigEndian.PutUint64(res[8:16], _z[2]) binary.BigEndian.PutUint64(res[0:8], _z[3]) return } // Marshal returns the regular (non montgomery) value // of z as a big-endian byte slice. func (z *Element) Marshal() []byte { b := z.Bytes() return b[:] } // SetBytes interprets e as the bytes of a big-endian unsigned integer, // sets z to that value (in Montgomery form), and returns z. func (z *Element) SetBytes(e []byte) *Element { // get a big int from our pool vv := bigIntPool.Get().(*big.Int) vv.SetBytes(e) // set big int z.SetBigInt(vv) // put temporary object back in pool bigIntPool.Put(vv) return z } // SetBigInt sets z to v (regular form) and returns z in Montgomery form func (z *Element) SetBigInt(v *big.Int) *Element { z.SetZero() var zero big.Int // fast path c := v.Cmp(&_modulus) if c == 0 { // v == 0 return z } else if c != 1 && v.Cmp(&zero) != -1 { // 0 < v < q return z.setBigInt(v) } // get temporary big int from the pool vv := bigIntPool.Get().(*big.Int) // copy input + modular reduction vv.Set(v) vv.Mod(v, &_modulus) // set big int byte value z.setBigInt(vv) // release object into pool bigIntPool.Put(vv) return z } // setBigInt assumes 0 <= v < q func (z *Element) setBigInt(v *big.Int) *Element { vBits := v.Bits() if bits.UintSize == 64 { for i := 0; i < len(vBits); i++ { z[i] = uint64(vBits[i]) } } else { for i := 0; i < len(vBits); i++ { if i%2 == 0 { z[i/2] = uint64(vBits[i]) } else { z[i/2] |= uint64(vBits[i]) << 32 } } } return z.ToMont() } // SetString creates a big.Int with s (in base 10) and calls SetBigInt on z func (z *Element) SetString(s string) *Element { // get temporary big int from the pool vv := bigIntPool.Get().(*big.Int) if _, ok := vv.SetString(s, 10); !ok { panic("Element.SetString failed -> can't parse number in base10 into a big.Int") } z.SetBigInt(vv) // release object into pool bigIntPool.Put(vv) return z } var ( _bLegendreExponentElement *big.Int _bSqrtExponentElement *big.Int ) func init() { _bLegendreExponentElement, _ = new(big.Int).SetString("183227397098d014dc2822db40c0ac2e9419f4243cdcb848a1f0fac9f8000000", 16) const sqrtExponentElement = "183227397098d014dc2822db40c0ac2e9419f4243cdcb848a1f0fac9f" _bSqrtExponentElement, _ = new(big.Int).SetString(sqrtExponentElement, 16) } // Legendre returns the Legendre symbol of z (either +1, -1, or 0.) func (z *Element) Legendre() int { var l Element // z^((q-1)/2) l.Exp(*z, _bLegendreExponentElement) if l.IsZero() { return 0 } // if l == 1 if (l[3] == 1011752739694698287) && (l[2] == 7381016538464732718) && (l[1] == 3962172157175319849) && (l[0] == 12436184717236109307) { return 1 } return -1 } // Sqrt z = √x mod q // if the square root doesn't exist (x is not a square mod q) // Sqrt leaves z unchanged and returns nil func (z *Element) Sqrt(x *Element) *Element { // q ≡ 1 (mod 4) // see modSqrtTonelliShanks in math/big/int.go // using https://www.maa.org/sites/default/files/pdf/upload_library/22/Polya/07468342.di020786.02p0470a.pdf var y, b, t, w Element // w = x^((s-1)/2)) w.Exp(*x, _bSqrtExponentElement) // y = x^((s+1)/2)) = w * x y.Mul(x, &w) // b = x^s = w * w * x = y * x b.Mul(&w, &y) // g = nonResidue ^ s var g = Element{ 7164790868263648668, 11685701338293206998, 6216421865291908056, 1756667274303109607, } r := uint64(28) // compute legendre symbol // t = x^((q-1)/2) = r-1 squaring of x^s t = b for i := uint64(0); i < r-1; i++ { t.Square(&t) } if t.IsZero() { return z.SetZero() } if !((t[3] == 1011752739694698287) && (t[2] == 7381016538464732718) && (t[1] == 3962172157175319849) && (t[0] == 12436184717236109307)) { // t != 1, we don't have a square root return nil } for { var m uint64 t = b // for t != 1 for !((t[3] == 1011752739694698287) && (t[2] == 7381016538464732718) && (t[1] == 3962172157175319849) && (t[0] == 12436184717236109307)) { t.Square(&t) m++ } if m == 0 { return z.Set(&y) } // t = g^(2^(r-m-1)) mod q ge := int(r - m - 1) t = g for ge > 0 { t.Square(&t) ge-- } g.Square(&t) y.Mul(&y, &t) b.Mul(&b, &g) r = m } } // Inverse z = x^-1 mod q // Algorithm 16 in "Efficient Software-Implementation of Finite Fields with Applications to Cryptography" // if x == 0, sets and returns z = x func (z *Element) Inverse(x *Element) *Element { if x.IsZero() { z.SetZero() return z } // initialize u = q var u = Element{ 4891460686036598785, 2896914383306846353, 13281191951274694749, 3486998266802970665, } // initialize s = r^2 var s = Element{ 1997599621687373223, 6052339484930628067, 10108755138030829701, 150537098327114917, } // r = 0 r := Element{} v := *x var carry, borrow uint64 var bigger bool for { for v[0]&1 == 0 { // v = v >> 1 v[0] = v[0]>>1 | v[1]<<63 v[1] = v[1]>>1 | v[2]<<63 v[2] = v[2]>>1 | v[3]<<63 v[3] >>= 1 if s[0]&1 == 1 { // s = s + q s[0], carry = bits.Add64(s[0], 4891460686036598785, 0) s[1], carry = bits.Add64(s[1], 2896914383306846353, carry) s[2], carry = bits.Add64(s[2], 13281191951274694749, carry) s[3], _ = bits.Add64(s[3], 3486998266802970665, carry) } // s = s >> 1 s[0] = s[0]>>1 | s[1]<<63 s[1] = s[1]>>1 | s[2]<<63 s[2] = s[2]>>1 | s[3]<<63 s[3] >>= 1 } for u[0]&1 == 0 { // u = u >> 1 u[0] = u[0]>>1 | u[1]<<63 u[1] = u[1]>>1 | u[2]<<63 u[2] = u[2]>>1 | u[3]<<63 u[3] >>= 1 if r[0]&1 == 1 { // r = r + q r[0], carry = bits.Add64(r[0], 4891460686036598785, 0) r[1], carry = bits.Add64(r[1], 2896914383306846353, carry) r[2], carry = bits.Add64(r[2], 13281191951274694749, carry) r[3], _ = bits.Add64(r[3], 3486998266802970665, carry) } // r = r >> 1 r[0] = r[0]>>1 | r[1]<<63 r[1] = r[1]>>1 | r[2]<<63 r[2] = r[2]>>1 | r[3]<<63 r[3] >>= 1 } // v >= u bigger = !(v[3] < u[3] || (v[3] == u[3] && (v[2] < u[2] || (v[2] == u[2] && (v[1] < u[1] || (v[1] == u[1] && (v[0] < u[0]))))))) if bigger { // v = v - u v[0], borrow = bits.Sub64(v[0], u[0], 0) v[1], borrow = bits.Sub64(v[1], u[1], borrow) v[2], borrow = bits.Sub64(v[2], u[2], borrow) v[3], _ = bits.Sub64(v[3], u[3], borrow) // s = s - r s[0], borrow = bits.Sub64(s[0], r[0], 0) s[1], borrow = bits.Sub64(s[1], r[1], borrow) s[2], borrow = bits.Sub64(s[2], r[2], borrow) s[3], borrow = bits.Sub64(s[3], r[3], borrow) if borrow == 1 { // s = s + q s[0], carry = bits.Add64(s[0], 4891460686036598785, 0) s[1], carry = bits.Add64(s[1], 2896914383306846353, carry) s[2], carry = bits.Add64(s[2], 13281191951274694749, carry) s[3], _ = bits.Add64(s[3], 3486998266802970665, carry) } } else { // u = u - v u[0], borrow = bits.Sub64(u[0], v[0], 0) u[1], borrow = bits.Sub64(u[1], v[1], borrow) u[2], borrow = bits.Sub64(u[2], v[2], borrow) u[3], _ = bits.Sub64(u[3], v[3], borrow) // r = r - s r[0], borrow = bits.Sub64(r[0], s[0], 0) r[1], borrow = bits.Sub64(r[1], s[1], borrow) r[2], borrow = bits.Sub64(r[2], s[2], borrow) r[3], borrow = bits.Sub64(r[3], s[3], borrow) if borrow == 1 { // r = r + q r[0], carry = bits.Add64(r[0], 4891460686036598785, 0) r[1], carry = bits.Add64(r[1], 2896914383306846353, carry) r[2], carry = bits.Add64(r[2], 13281191951274694749, carry) r[3], _ = bits.Add64(r[3], 3486998266802970665, carry) } } if (u[0] == 1) && (u[3]|u[2]|u[1]) == 0 { z.Set(&r) return z } if (v[0] == 1) && (v[3]|v[2]|v[1]) == 0 { z.Set(&s) return z } } }