arnaucube
arnaucube/go-snarkPublic Self-hosted repository
go-snark/fields/fq.go
fields/fq.goRaw
  1package fields
  2
  3import (
  4	"bytes"
  5	"math/big"
  6)
  7
  8// Fq is the Z field over modulus Q
  9type Fq struct {
 10	Q *big.Int // Q
 11}
 12
 13// NewFq generates a new Fq
 14func NewFq(q *big.Int) Fq {
 15	return Fq{
 16		q,
 17	}
 18}
 19
 20// Zero returns a Zero value on the Fq
 21func (fq Fq) Zero() *big.Int {
 22	return big.NewInt(int64(0))
 23}
 24
 25// One returns a One value on the Fq
 26func (fq Fq) One() *big.Int {
 27	return big.NewInt(int64(1))
 28}
 29
 30// Add performs an addition on the Fq
 31func (fq Fq) Add(a, b *big.Int) *big.Int {
 32	r := new(big.Int).Add(a, b)
 33	return new(big.Int).Mod(r, fq.Q)
 34	// return r
 35}
 36
 37// Double performs a doubling on the Fq
 38func (fq Fq) Double(a *big.Int) *big.Int {
 39	r := new(big.Int).Add(a, a)
 40	return new(big.Int).Mod(r, fq.Q)
 41	// return r
 42}
 43
 44// Sub performs a subtraction on the Fq
 45func (fq Fq) Sub(a, b *big.Int) *big.Int {
 46	r := new(big.Int).Sub(a, b)
 47	return new(big.Int).Mod(r, fq.Q)
 48	// return r
 49}
 50
 51// Neg performs a negation on the Fq
 52func (fq Fq) Neg(a *big.Int) *big.Int {
 53	m := new(big.Int).Neg(a)
 54	return new(big.Int).Mod(m, fq.Q)
 55	// return m
 56}
 57
 58// Mul performs a multiplication on the Fq
 59func (fq Fq) Mul(a, b *big.Int) *big.Int {
 60	m := new(big.Int).Mul(a, b)
 61	return new(big.Int).Mod(m, fq.Q)
 62	// return m
 63}
 64
 65func (fq Fq) MulScalar(base, e *big.Int) *big.Int {
 66	return fq.Mul(base, e)
 67}
 68
 69// Inverse returns the inverse on the Fq
 70func (fq Fq) Inverse(a *big.Int) *big.Int {
 71	return new(big.Int).ModInverse(a, fq.Q)
 72	// q := bigCopy(fq.Q)
 73	// t := big.NewInt(int64(0))
 74	// r := fq.Q
 75	// newt := big.NewInt(int64(0))
 76	// newr := fq.Affine(a)
 77	// for !bytes.Equal(newr.Bytes(), big.NewInt(int64(0)).Bytes()) {
 78	// 	q := new(big.Int).Div(bigCopy(r), bigCopy(newr))
 79	//
 80	// 	t = bigCopy(newt)
 81	// 	newt = fq.Sub(t, fq.Mul(q, newt))
 82	//
 83	// 	r = bigCopy(newr)
 84	// 	newr = fq.Sub(r, fq.Mul(q, newr))
 85	// }
 86	// if t.Cmp(big.NewInt(0)) == -1 { // t< 0
 87	// 	t = fq.Add(t, q)
 88	// }
 89	// return t
 90}
 91
 92// Div performs the division over the finite field
 93func (fq Fq) Div(a, b *big.Int) *big.Int {
 94	d := fq.Mul(a, fq.Inverse(b))
 95	return new(big.Int).Mod(d, fq.Q)
 96}
 97
 98// Square performs a square operation on the Fq
 99func (fq Fq) Square(a *big.Int) *big.Int {
100	m := new(big.Int).Mul(a, a)
101	return new(big.Int).Mod(m, fq.Q)
102}
103
104// Exp performs the exponential over Fq
105func (fq Fq) Exp(base *big.Int, e *big.Int) *big.Int {
106	res := fq.One()
107	rem := fq.Copy(e)
108	exp := base
109
110	for !bytes.Equal(rem.Bytes(), big.NewInt(int64(0)).Bytes()) {
111		if BigIsOdd(rem) {
112			res = fq.Mul(res, exp)
113		}
114		exp = fq.Square(exp)
115		rem = new(big.Int).Rsh(rem, 1)
116	}
117	return res
118}
119
120func (fq Fq) IsZero(a *big.Int) bool {
121	return bytes.Equal(a.Bytes(), fq.Zero().Bytes())
122}
123
124func (fq Fq) Copy(a *big.Int) *big.Int {
125	return new(big.Int).SetBytes(a.Bytes())
126}
127
128func (fq Fq) Affine(a *big.Int) *big.Int {
129	nq := fq.Neg(fq.Q)
130
131	aux := a
132	if aux.Cmp(big.NewInt(int64(0))) == -1 { // negative value
133		if aux.Cmp(nq) != 1 { // aux less or equal nq
134			aux = new(big.Int).Mod(aux, fq.Q)
135		}
136		if aux.Cmp(big.NewInt(int64(0))) == -1 { // negative value
137			aux = new(big.Int).Add(aux, fq.Q)
138		}
139	} else {
140		if aux.Cmp(fq.Q) != -1 { // aux greater or equal nq
141			aux = new(big.Int).Mod(aux, fq.Q)
142		}
143	}
144	return aux
145}
146
147func (fq Fq) Equal(a, b *big.Int) bool {
148	aAff := fq.Affine(a)
149	bAff := fq.Affine(b)
150	return bytes.Equal(aAff.Bytes(), bAff.Bytes())
151}