-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathfield.go
119 lines (94 loc) · 2.7 KB
/
field.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
package algebra
import (
"crypto/rand"
"math/big"
)
type Field struct {
P *big.Int // field modulus
}
type FieldElement struct {
Int *big.Int
}
// new field of order p
func NewField(p *big.Int) *Field {
return &Field{P: p}
}
// add modulo P
func (f *Field) Add(a, b *FieldElement) *FieldElement {
newValue := new(big.Int).Mod(new(big.Int).Add(a.Int, b.Int), f.P)
return f.NewElement(newValue)
}
func (f *Field) AddInplace(a *FieldElement, b *FieldElement) {
a.Int.Add(a.Int, b.Int).Mod(a.Int, f.P)
}
// sub modulo P
func (f *Field) Sub(a, b *FieldElement) *FieldElement {
newValue := new(big.Int).Mod(new(big.Int).Sub(a.Int, b.Int), f.P)
return f.NewElement(newValue)
}
func (f *Field) SubInplace(a *FieldElement, b *FieldElement) {
a.Int.Sub(a.Int, b.Int).Mod(a.Int, f.P)
}
func (f *Field) Negate(a *FieldElement) *FieldElement {
newValue := new(big.Int).Mod(new(big.Int).Sub(f.P, a.Int), f.P)
return f.NewElement(newValue)
}
// return multiplicative inverse with mod P
func (f *Field) MulInv(a *FieldElement) *FieldElement {
newValue := new(big.Int).ModInverse(a.Int, f.P)
return f.NewElement(newValue)
}
// multiply mod P
func (f *Field) Mul(a, b *FieldElement) *FieldElement {
newValue := new(big.Int).Mul(a.Int, b.Int)
return f.NewElement(newValue)
}
func (f *Field) MulInplace(a *FieldElement, b *FieldElement) {
a.Int.Mul(a.Int, b.Int).Mod(a.Int, f.P)
}
// exponentiation mod P
func (f *Field) Exp(a *FieldElement, c *big.Int) *FieldElement {
newValue := exp(a.Int, c, f.P)
return f.NewElement(newValue)
}
func (f *Field) ExpInplace(a *FieldElement, c *big.Int) {
expInplace(a.Int, c, f.P)
}
// new element (a mod P)
func (f *Field) NewElement(a *big.Int) *FieldElement {
newValue := new(big.Int).Mod(a, f.P)
return &FieldElement{newValue}
}
// returns a random element in the field
func (f *Field) RandomElement() *FieldElement {
a := randomInt(f.P)
return f.NewElement(a)
}
func (f *Field) AddIdentity() *FieldElement {
return &FieldElement{big.NewInt(0)}
}
func (f *Field) MulIdentity() *FieldElement {
return &FieldElement{big.NewInt(1)}
}
func (f *Field) IsAddIdentity(e *FieldElement) bool {
return f.AddIdentity().Cmp(e) == 0
}
func (f *Field) IsMulIdentity(e *FieldElement) bool {
return f.MulIdentity().Cmp(e) == 0
}
func (f *Field) IsZero(e *FieldElement) bool {
return f.AddIdentity().Cmp(e) == 0
}
func (elem *FieldElement) Cmp(b *FieldElement) int {
return elem.Int.Cmp(b.Int)
}
func randomInt(max *big.Int) *big.Int {
randomBig, _ := rand.Int(rand.Reader, new(big.Int).SetBytes(max.Bytes()))
return new(big.Int).SetBytes(randomBig.Bytes())
}
func exp(a, b, n *big.Int) *big.Int {
return new(big.Int).Exp(a, b, n)
}
func expInplace(a, b, n *big.Int) {
new(big.Int).Exp(a, b, n)
}