arnaucube
arnaucube/go-snarkPublic Self-hosted repository
go-snark/fields/fq6.go
fields/fq6.goRaw
  1package fields
  2
  3import (
  4	"bytes"
  5	"math/big"
  6)
  7
  8// Fq6 is Field 6
  9type Fq6 struct {
 10	F          Fq2
 11	NonResidue [2]*big.Int
 12}
 13
 14// NewFq6 generates a new Fq6
 15func NewFq6(f Fq2, nonResidue [2]*big.Int) Fq6 {
 16	fq6 := Fq6{
 17		f,
 18		nonResidue,
 19	}
 20	return fq6
 21}
 22
 23// Zero returns a Zero value on the Fq6
 24func (fq6 Fq6) Zero() [3][2]*big.Int {
 25	return [3][2]*big.Int{fq6.F.Zero(), fq6.F.Zero(), fq6.F.Zero()}
 26}
 27
 28// One returns a One value on the Fq6
 29func (fq6 Fq6) One() [3][2]*big.Int {
 30	return [3][2]*big.Int{fq6.F.One(), fq6.F.Zero(), fq6.F.Zero()}
 31}
 32
 33func (fq6 Fq6) mulByNonResidue(a [2]*big.Int) [2]*big.Int {
 34	return fq6.F.Mul(fq6.NonResidue, a)
 35}
 36
 37// Add performs an addition on the Fq6
 38func (fq6 Fq6) Add(a, b [3][2]*big.Int) [3][2]*big.Int {
 39	return [3][2]*big.Int{
 40		fq6.F.Add(a[0], b[0]),
 41		fq6.F.Add(a[1], b[1]),
 42		fq6.F.Add(a[2], b[2]),
 43	}
 44}
 45
 46func (fq6 Fq6) Double(a [3][2]*big.Int) [3][2]*big.Int {
 47	return fq6.Add(a, a)
 48}
 49
 50// Sub performs a subtraction on the Fq6
 51func (fq6 Fq6) Sub(a, b [3][2]*big.Int) [3][2]*big.Int {
 52	return [3][2]*big.Int{
 53		fq6.F.Sub(a[0], b[0]),
 54		fq6.F.Sub(a[1], b[1]),
 55		fq6.F.Sub(a[2], b[2]),
 56	}
 57}
 58
 59// Neg performs a negation on the Fq6
 60func (fq6 Fq6) Neg(a [3][2]*big.Int) [3][2]*big.Int {
 61	return fq6.Sub(fq6.Zero(), a)
 62}
 63
 64// Mul performs a multiplication on the Fq6
 65func (fq6 Fq6) Mul(a, b [3][2]*big.Int) [3][2]*big.Int {
 66	v0 := fq6.F.Mul(a[0], b[0])
 67	v1 := fq6.F.Mul(a[1], b[1])
 68	v2 := fq6.F.Mul(a[2], b[2])
 69	return [3][2]*big.Int{
 70		fq6.F.Add(
 71			v0,
 72			fq6.mulByNonResidue(
 73				fq6.F.Sub(
 74					fq6.F.Mul(
 75						fq6.F.Add(a[1], a[2]),
 76						fq6.F.Add(b[1], b[2])),
 77					fq6.F.Add(v1, v2)))),
 78
 79		fq6.F.Add(
 80			fq6.F.Sub(
 81				fq6.F.Mul(
 82					fq6.F.Add(a[0], a[1]),
 83					fq6.F.Add(b[0], b[1])),
 84				fq6.F.Add(v0, v1)),
 85			fq6.mulByNonResidue(v2)),
 86
 87		fq6.F.Add(
 88			fq6.F.Sub(
 89				fq6.F.Mul(
 90					fq6.F.Add(a[0], a[2]),
 91					fq6.F.Add(b[0], b[2])),
 92				fq6.F.Add(v0, v2)),
 93			v1),
 94	}
 95}
 96
 97func (fq6 Fq6) MulScalar(base [3][2]*big.Int, e *big.Int) [3][2]*big.Int {
 98	// for more possible implementations see g2.go file, at the function g2.MulScalar()
 99
100	res := fq6.Zero()
101	rem := e
102	exp := base
103
104	for !bytes.Equal(rem.Bytes(), big.NewInt(int64(0)).Bytes()) {
105		// if rem % 2 == 1
106		if bytes.Equal(new(big.Int).Rem(rem, big.NewInt(int64(2))).Bytes(), big.NewInt(int64(1)).Bytes()) {
107			res = fq6.Add(res, exp)
108		}
109		exp = fq6.Double(exp)
110		rem = rem.Rsh(rem, 1) // rem = rem >> 1
111	}
112	return res
113}
114
115// Inverse returns the inverse on the Fq6
116func (fq6 Fq6) Inverse(a [3][2]*big.Int) [3][2]*big.Int {
117	t0 := fq6.F.Square(a[0])
118	t1 := fq6.F.Square(a[1])
119	t2 := fq6.F.Square(a[2])
120	t3 := fq6.F.Mul(a[0], a[1])
121	t4 := fq6.F.Mul(a[0], a[2])
122	t5 := fq6.F.Mul(a[1], a[2])
123
124	c0 := fq6.F.Sub(t0, fq6.mulByNonResidue(t5))
125	c1 := fq6.F.Sub(fq6.mulByNonResidue(t2), t3)
126	c2 := fq6.F.Sub(t1, t4)
127
128	t6 := fq6.F.Inverse(
129		fq6.F.Add(
130			fq6.F.Mul(a[0], c0),
131			fq6.mulByNonResidue(
132				fq6.F.Add(
133					fq6.F.Mul(a[2], c1),
134					fq6.F.Mul(a[1], c2)))))
135	return [3][2]*big.Int{
136		fq6.F.Mul(t6, c0),
137		fq6.F.Mul(t6, c1),
138		fq6.F.Mul(t6, c2),
139	}
140}
141
142// Div performs a division on the Fq6
143func (fq6 Fq6) Div(a, b [3][2]*big.Int) [3][2]*big.Int {
144	return fq6.Mul(a, fq6.Inverse(b))
145}
146
147// Square performs a square operation on the Fq6
148func (fq6 Fq6) Square(a [3][2]*big.Int) [3][2]*big.Int {
149	s0 := fq6.F.Square(a[0])
150	ab := fq6.F.Mul(a[0], a[1])
151	s1 := fq6.F.Add(ab, ab)
152	s2 := fq6.F.Square(
153		fq6.F.Add(
154			fq6.F.Sub(a[0], a[1]),
155			a[2]))
156	bc := fq6.F.Mul(a[1], a[2])
157	s3 := fq6.F.Add(bc, bc)
158	s4 := fq6.F.Square(a[2])
159
160	return [3][2]*big.Int{
161		fq6.F.Add(
162			s0,
163			fq6.mulByNonResidue(s3)),
164		fq6.F.Add(
165			s1,
166			fq6.mulByNonResidue(s4)),
167		fq6.F.Sub(
168			fq6.F.Add(
169				fq6.F.Add(s1, s2),
170				s3),
171			fq6.F.Add(s0, s4)),
172	}
173}
174
175func (fq6 Fq6) Affine(a [3][2]*big.Int) [3][2]*big.Int {
176	return [3][2]*big.Int{
177		fq6.F.Affine(a[0]),
178		fq6.F.Affine(a[1]),
179		fq6.F.Affine(a[2]),
180	}
181}
182func (fq6 Fq6) Equal(a, b [3][2]*big.Int) bool {
183	return fq6.F.Equal(a[0], b[0]) && fq6.F.Equal(a[1], b[1]) && fq6.F.Equal(a[2], b[2])
184}
185
186func (fq6 Fq6) Copy(a [3][2]*big.Int) [3][2]*big.Int {
187	return [3][2]*big.Int{
188		fq6.F.Copy(a[0]),
189		fq6.F.Copy(a[1]),
190		fq6.F.Copy(a[2]),
191	}
192}