|
|
// 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 ffg
// /!\ WARNING /!\
// this code has not been audited and is provided as-is. In particular,
// there is no security guarantees such as constant time implementation
// or side-channel attack resistance
// /!\ WARNING /!\
import ( "crypto/rand" "encoding/binary" "errors" "io" "math/big" "math/bits" "reflect" "strconv" "sync" )
// Element represents a field element stored on 1 words (uint64)
// Element are assumed to be in Montgomery form in all methods
// field modulus q =
//
// 18446744069414584321
type Element [1]uint64
// Limbs number of 64 bits words needed to represent Element
const Limbs = 1
// Bits number bits needed to represent Element
const Bits = 64
// 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 =
//
// 18446744069414584321
func Modulus() *big.Int { return new(big.Int).Set(&_modulus) }
// q (modulus)
var qElement = Element{ 18446744069414584321, }
// rSquare
var rSquare = Element{ 18446744065119617025, }
var bigIntPool = sync.Pool{ New: func() interface{} { return new(big.Int) }, }
func init() { _modulus.SetString("18446744069414584321", 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] 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 ffg.Element from type " + reflect.TypeOf(i1).String()) } }
// SetZero z = 0
func (z *Element) SetZero() *Element { z[0] = 0 return z }
// SetOne z = 1 (in Montgomery form)
func (z *Element) SetOne() *Element { z[0] = 4294967295 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 >= 1 { return 0 } return uint64(z[j] >> (i % 64) & 1) }
// Equal returns z == x
func (z *Element) Equal(x *Element) bool { return (z[0] == x[0]) }
// IsZero returns z == 0
func (z *Element) IsZero() bool { return (z[0]) == 0 }
// IsUint64 returns true if z[0] >= 0 and all other words are 0
func (z *Element) IsUint64() bool { // return () == 0
return true }
// 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[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], 9223372034707292161, 0)
return b == 0 }
// SetRandom sets z to a random element < q
func (z *Element) SetRandom() (*Element, error) { var bytes [8]byte if _, err := io.ReadFull(rand.Reader, bytes[:]); err != nil { return nil, err } z[0] = binary.BigEndian.Uint64(bytes[0:8]) z[0] %= 18446744069414584321
// if z > q --> z -= q
// note: this is NOT constant time
if !(z[0] < 18446744069414584321) { // var b uint64
z[0], _ = bits.Sub64(z[0], 18446744069414584321, 0) }
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() { var twoInv Element twoInv.SetOne().Double(&twoInv).Inverse(&twoInv) z.Mul(z, &twoInv)
}
// 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 [2]uint64 var D uint64 var m, C uint64 // -----------------------------------
// First loop
C, t[0] = bits.Mul64(y[0], x[0])
t[1], D = bits.Add64(t[1], C, 0)
// m = t[0]n'[0] mod W
m = t[0] * 18446744069414584319
// -----------------------------------
// Second loop
C = madd0(m, 18446744069414584321, t[0])
t[0], C = bits.Add64(t[1], C, 0) t[1], _ = bits.Add64(0, D, C)
if t[1] != 0 { // we need to reduce, we have a result on 2 words
// var b uint64
z[0], _ = bits.Sub64(t[0], 18446744069414584321, 0)
return
}
// copy t into z
z[0] = t[0]
// if z > q --> z -= q
// note: this is NOT constant time
if !(z[0] < 18446744069414584321) { // var b uint64
z[0], _ = bits.Sub64(z[0], 18446744069414584321, 0) } }
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] * 18446744069414584319 C := madd0(m, 18446744069414584321, z[0]) z[0] = C }
// if z > q --> z -= q
// note: this is NOT constant time
if !(z[0] < 18446744069414584321) { // var b uint64
z[0], _ = bits.Sub64(z[0], 18446744069414584321, 0) } }
func _addGeneric(z, x, y *Element) { var carry uint64
z[0], carry = bits.Add64(x[0], y[0], 0) // if we overflowed the last addition, z >= q
// if z >= q, z = z - q
if carry != 0 { // we overflowed, so z >= q
z[0], _ = bits.Sub64(z[0], 18446744069414584321, 0) return }
// if z > q --> z -= q
// note: this is NOT constant time
if !(z[0] < 18446744069414584321) { // var b uint64
z[0], _ = bits.Sub64(z[0], 18446744069414584321, 0) } }
func _doubleGeneric(z, x *Element) { var carry uint64
z[0], carry = bits.Add64(x[0], x[0], 0) // if we overflowed the last addition, z >= q
// if z >= q, z = z - q
if carry != 0 { // we overflowed, so z >= q
z[0], _ = bits.Sub64(z[0], 18446744069414584321, 0) return }
// if z > q --> z -= q
// note: this is NOT constant time
if !(z[0] < 18446744069414584321) { // var b uint64
z[0], _ = bits.Sub64(z[0], 18446744069414584321, 0) } }
func _subGeneric(z, x, y *Element) { var b uint64 z[0], b = bits.Sub64(x[0], y[0], 0) if b != 0 { // var c uint64
z[0], _ = bits.Add64(z[0], 18446744069414584321, 0) } }
func _negGeneric(z, x *Element) { if x.IsZero() { z.SetZero() return } // var borrow uint64
z[0], _ = bits.Sub64(18446744069414584321, x[0], 0) }
func _reduceGeneric(z *Element) {
// if z > q --> z -= q
// note: this is NOT constant time
if !(z[0] < 18446744069414584321) { // var b uint64
z[0], _ = bits.Sub64(z[0], 18446744069414584321, 0) } }
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 { 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[0:8], z[0])
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) }
// ToUint64Regular returns z as a uint64 in regular form
func (z Element) ToUint64Regular() uint64 { z.FromMont() return z[0] }
// 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[0:8], _z[0])
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("7fffffff80000000", 16) const sqrtExponentElement = "7fffffff" _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[0] == 4294967295 { 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{ 15733474329512464024, } r := uint64(32)
// 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[0] == 4294967295) { // t != 1, we don't have a square root
return nil } for { var m uint64 t = b
// for t != 1
for !(t[0] == 4294967295) { 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
// note: allocates a big.Int (math/big)
func (z *Element) Inverse(x *Element) *Element { var _xNonMont big.Int x.ToBigIntRegular(&_xNonMont) _xNonMont.ModInverse(&_xNonMont, Modulus()) z.SetBigInt(&_xNonMont) return z }
|