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}