func (z *Element) SetBigInt(v *big.Int) *Element {
	z.SetZero()
	zero := big.NewInt(0)
	q := ElementModulus()
	c := v.Cmp(q)
	if c == 0 {
		return z
	} else if c != 1 && v.Cmp(zero) != -1 {
		vBits := v.Bits()
		for i := 0; i < len(vBits); i++ {
			z[i] = uint64(vBits[i])
		}
		return z.ToMont()
	}
	vv := new(big.Int).Set(v)
	vv.Mod(v, q)
	vBits := vv.Bits()
	for i := 0; i < len(vBits); i++ {
		z[i] = uint64(vBits[i])
	}
	return z.ToMont()
}
SetBigInt sets z to v (regular form) and returns z in Montgomery form
package fr
import (
	"crypto/rand"
	"encoding/binary"
	"io"
	"math/big"
	"math/bits"
	"strconv"
	"sync"
	"unsafe"
)
type Element [4]uint64
const ElementLimbs = 4
const ElementBits = 255
func (z *Element) Bytes() []byte {
	var _z Element
	_z.Set(z).FromMont()
	res := make([]byte, ElementLimbs*8)
	binary.BigEndian.PutUint64(res[(ElementLimbs-1)*8:], _z[0])
	for i := ElementLimbs - 2; i >= 0; i-- {
		binary.BigEndian.PutUint64(res[i*8:(i+1)*8], _z[ElementLimbs-1-i])
	}
	return res
}
func (z *Element) SetBytes(e []byte) *Element {
	var tmp big.Int
	tmp.SetBytes(e)
	z.SetBigInt(&tmp)
	return z
}
func (z *Element) SetUint64(v uint64) *Element {
	z[0] = v
	z[1] = 0
	z[2] = 0
	z[3] = 0
	return z.ToMont()
}
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
}
func (z *Element) SetZero() *Element {
	z[0] = 0
	z[1] = 0
	z[2] = 0
	z[3] = 0
	return z
}
func (z *Element) SetOne() *Element {
	z[0] = 8589934590
	z[1] = 6378425256633387010
	z[2] = 11064306276430008309
	z[3] = 1739710354780652911
	return z
}
func (z *Element) Neg(x *Element) *Element {
	if x.IsZero() {
		return z.SetZero()
	}
	var borrow uint64
	z[0], borrow = bits.Sub64(18446744069414584321, x[0], 0)
	z[1], borrow = bits.Sub64(6034159408538082302, x[1], borrow)
	z[2], borrow = bits.Sub64(3691218898639771653, x[2], borrow)
	z[3], _ = bits.Sub64(8353516859464449352, x[3], borrow)
	return z
}
func (z *Element) Div(x, y *Element) *Element {
	var yInv Element
	yInv.Inverse(y)
	z.Mul(x, &yInv)
	return z
}
func (z *Element) Equal(x *Element) bool {
	return (z[3] == x[3]) && (z[2] == x[2]) && (z[1] == x[1]) && (z[0] == x[0])
}
func (z *Element) IsZero() bool {
	return (z[3] | z[2] | z[1] | z[0]) == 0
}
var _ElementModulus big.Int
var onceElementModulus sync.Once
func ElementModulus() *big.Int {
	onceElementModulus.Do(func() {
		_ElementModulus.SetString("52435875175126190479447740508185965837690552500527637822603658699938581184513", 10)
	})
	return &_ElementModulus
}
func (z *Element) Inverse(x *Element) *Element {
	if x.IsZero() {
		return z.Set(x)
	}
	var u = Element{
		18446744069414584321,
		6034159408538082302,
		3691218898639771653,
		8353516859464449352,
	}
	var s = Element{
		14526898881837571181,
		3129137299524312099,
		419701826671360399,
		524908885293268753,
	}
	r := Element{}
	v := *x
	var carry, borrow, t, t2 uint64
	var bigger, uIsOne, vIsOne bool
	for !uIsOne && !vIsOne {
		for v[0]&1 == 0 {
			t2 = v[3] << 63
			v[3] >>= 1
			t = t2
			t2 = v[2] << 63
			v[2] = (v[2] >> 1) | t
			t = t2
			t2 = v[1] << 63
			v[1] = (v[1] >> 1) | t
			t = t2
			v[0] = (v[0] >> 1) | t
			if s[0]&1 == 1 {
				s[0], carry = bits.Add64(s[0], 18446744069414584321, 0)
				s[1], carry = bits.Add64(s[1], 6034159408538082302, carry)
				s[2], carry = bits.Add64(s[2], 3691218898639771653, carry)
				s[3], _ = bits.Add64(s[3], 8353516859464449352, carry)
			}
			t2 = s[3] << 63
			s[3] >>= 1
			t = t2
			t2 = s[2] << 63
			s[2] = (s[2] >> 1) | t
			t = t2
			t2 = s[1] << 63
			s[1] = (s[1] >> 1) | t
			t = t2
			s[0] = (s[0] >> 1) | t
		}
		for u[0]&1 == 0 {
			t2 = u[3] << 63
			u[3] >>= 1
			t = t2
			t2 = u[2] << 63
			u[2] = (u[2] >> 1) | t
			t = t2
			t2 = u[1] << 63
			u[1] = (u[1] >> 1) | t
			t = t2
			u[0] = (u[0] >> 1) | t
			if r[0]&1 == 1 {
				r[0], carry = bits.Add64(r[0], 18446744069414584321, 0)
				r[1], carry = bits.Add64(r[1], 6034159408538082302, carry)
				r[2], carry = bits.Add64(r[2], 3691218898639771653, carry)
				r[3], _ = bits.Add64(r[3], 8353516859464449352, carry)
			}
			t2 = r[3] << 63
			r[3] >>= 1
			t = t2
			t2 = r[2] << 63
			r[2] = (r[2] >> 1) | t
			t = t2
			t2 = r[1] << 63
			r[1] = (r[1] >> 1) | t
			t = t2
			r[0] = (r[0] >> 1) | t
		}
		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[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)
			bigger = !(r[3] < s[3] || (r[3] == s[3] && (r[2] < s[2] || (r[2] == s[2] && (r[1] < s[1] || (r[1] == s[1] && (r[0] < s[0])))))))
			if bigger {
				s[0], carry = bits.Add64(s[0], 18446744069414584321, 0)
				s[1], carry = bits.Add64(s[1], 6034159408538082302, carry)
				s[2], carry = bits.Add64(s[2], 3691218898639771653, carry)
				s[3], _ = bits.Add64(s[3], 8353516859464449352, carry)
			}
			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], _ = bits.Sub64(s[3], r[3], borrow)
		} else {
			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)
			bigger = !(s[3] < r[3] || (s[3] == r[3] && (s[2] < r[2] || (s[2] == r[2] && (s[1] < r[1] || (s[1] == r[1] && (s[0] < r[0])))))))
			if bigger {
				r[0], carry = bits.Add64(r[0], 18446744069414584321, 0)
				r[1], carry = bits.Add64(r[1], 6034159408538082302, carry)
				r[2], carry = bits.Add64(r[2], 3691218898639771653, carry)
				r[3], _ = bits.Add64(r[3], 8353516859464449352, carry)
			}
			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], _ = bits.Sub64(r[3], s[3], borrow)
		}
		uIsOne = (u[0] == 1) && (u[3]|u[2]|u[1]) == 0
		vIsOne = (v[0] == 1) && (v[3]|v[2]|v[1]) == 0
	}
	if uIsOne {
		z.Set(&r)
	} else {
		z.Set(&s)
	}
	return z
}
func (z *Element) SetRandom() *Element {
	bytes := make([]byte, 32)
	io.ReadFull(rand.Reader, bytes)
	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] %= 8353516859464449352
	if !(z[3] < 8353516859464449352 || (z[3] == 8353516859464449352 && (z[2] < 3691218898639771653 || (z[2] == 3691218898639771653 && (z[1] < 6034159408538082302 || (z[1] == 6034159408538082302 && (z[0] < 18446744069414584321))))))) {
		var b uint64
		z[0], b = bits.Sub64(z[0], 18446744069414584321, 0)
		z[1], b = bits.Sub64(z[1], 6034159408538082302, b)
		z[2], b = bits.Sub64(z[2], 3691218898639771653, b)
		z[3], _ = bits.Sub64(z[3], 8353516859464449352, b)
	}
	return z
}
func One() Element {
	var one Element
	one.SetOne()
	return one
}
func FromInterface(i1 interface{}) Element {
	var val Element
	switch c1 := i1.(type) {
	case uint64:
		val.SetUint64(c1)
	case int:
		val.SetString(strconv.Itoa(c1))
	case string:
		val.SetString(c1)
	case big.Int:
		val.SetBigInt(&c1)
	case Element:
		val = c1
	case *Element:
		val.Set(c1)
	case []byte:
		val.SetBytes(c1)
	default:
		panic("invalid type")
	}
	return val
}
func (z *Element) Add(x, y *Element) *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[3] < 8353516859464449352 || (z[3] == 8353516859464449352 && (z[2] < 3691218898639771653 || (z[2] == 3691218898639771653 && (z[1] < 6034159408538082302 || (z[1] == 6034159408538082302 && (z[0] < 18446744069414584321))))))) {
		var b uint64
		z[0], b = bits.Sub64(z[0], 18446744069414584321, 0)
		z[1], b = bits.Sub64(z[1], 6034159408538082302, b)
		z[2], b = bits.Sub64(z[2], 3691218898639771653, b)
		z[3], _ = bits.Sub64(z[3], 8353516859464449352, b)
	}
	return z
}
func (z *Element) AddAssign(x *Element) *Element {
	var carry uint64
	z[0], carry = bits.Add64(z[0], x[0], 0)
	z[1], carry = bits.Add64(z[1], x[1], carry)
	z[2], carry = bits.Add64(z[2], x[2], carry)
	z[3], _ = bits.Add64(z[3], x[3], carry)
	if !(z[3] < 8353516859464449352 || (z[3] == 8353516859464449352 && (z[2] < 3691218898639771653 || (z[2] == 3691218898639771653 && (z[1] < 6034159408538082302 || (z[1] == 6034159408538082302 && (z[0] < 18446744069414584321))))))) {
		var b uint64
		z[0], b = bits.Sub64(z[0], 18446744069414584321, 0)
		z[1], b = bits.Sub64(z[1], 6034159408538082302, b)
		z[2], b = bits.Sub64(z[2], 3691218898639771653, b)
		z[3], _ = bits.Sub64(z[3], 8353516859464449352, b)
	}
	return z
}
func (z *Element) Double(x *Element) *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[3] < 8353516859464449352 || (z[3] == 8353516859464449352 && (z[2] < 3691218898639771653 || (z[2] == 3691218898639771653 && (z[1] < 6034159408538082302 || (z[1] == 6034159408538082302 && (z[0] < 18446744069414584321))))))) {
		var b uint64
		z[0], b = bits.Sub64(z[0], 18446744069414584321, 0)
		z[1], b = bits.Sub64(z[1], 6034159408538082302, b)
		z[2], b = bits.Sub64(z[2], 3691218898639771653, b)
		z[3], _ = bits.Sub64(z[3], 8353516859464449352, b)
	}
	return z
}
func (z *Element) Sub(x, y *Element) *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], 18446744069414584321, 0)
		z[1], c = bits.Add64(z[1], 6034159408538082302, c)
		z[2], c = bits.Add64(z[2], 3691218898639771653, c)
		z[3], _ = bits.Add64(z[3], 8353516859464449352, c)
	}
	return z
}
func (z *Element) SubAssign(x *Element) *Element {
	var b uint64
	z[0], b = bits.Sub64(z[0], x[0], 0)
	z[1], b = bits.Sub64(z[1], x[1], b)
	z[2], b = bits.Sub64(z[2], x[2], b)
	z[3], b = bits.Sub64(z[3], x[3], b)
	if b != 0 {
		var c uint64
		z[0], c = bits.Add64(z[0], 18446744069414584321, 0)
		z[1], c = bits.Add64(z[1], 6034159408538082302, c)
		z[2], c = bits.Add64(z[2], 3691218898639771653, c)
		z[3], _ = bits.Add64(z[3], 8353516859464449352, c)
	}
	return z
}
func (z *Element) Exp(x Element, exponent ...uint64) *Element {
	r := 0
	msb := 0
	for i := len(exponent) - 1; i >= 0; i-- {
		if exponent[i] == 0 {
			r++
		} else {
			msb = (i * 64) + bits.Len64(exponent[i])
			break
		}
	}
	exponent = exponent[:len(exponent)-r]
	if len(exponent) == 0 {
		return z.SetOne()
	}
	z.Set(&x)
	l := msb - 2
	for i := l; i >= 0; i-- {
		z.Square(z)
		if exponent[i/64]&(1<<uint(i%64)) != 0 {
			z.MulAssign(&x)
		}
	}
	return z
}
func (z *Element) FromMont() *Element {
	fromMontElement(z)
	return z
}
func (z *Element) ToMont() *Element {
	var rSquare = Element{
		14526898881837571181,
		3129137299524312099,
		419701826671360399,
		524908885293268753,
	}
	mulAssignElement(z, &rSquare)
	return z
}
func (z Element) ToRegular() Element {
	return *z.FromMont()
}
func (z *Element) String() string {
	var _z big.Int
	return z.ToBigIntRegular(&_z).String()
}
func (z *Element) ToBigInt(res *big.Int) *big.Int {
	bits := (*[4]big.Word)(unsafe.Pointer(z))
	return res.SetBits(bits[:])
}
func (z Element) ToBigIntRegular(res *big.Int) *big.Int {
	z.FromMont()
	bits := (*[4]big.Word)(unsafe.Pointer(&z))
	return res.SetBits(bits[:])
}