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}