go-snark/r1csqapFloat/r1csqapFloat.go
r1csqapFloat/r1csqapFloat.goRaw
1package r1csqapFloat
2
3import "math/big"
4
5func Transpose(matrix [][]*big.Float) [][]*big.Float {
6 var r [][]*big.Float
7 for i := 0; i < len(matrix[0]); i++ {
8 var row []*big.Float
9 for j := 0; j < len(matrix); j++ {
10 row = append(row, matrix[j][i])
11 }
12 r = append(r, row)
13 }
14 return r
15}
16
17func ArrayOfBigZeros(num int) []*big.Float {
18 bigZero := big.NewFloat(float64(0))
19 var r []*big.Float
20 for i := 0; i < num; i++ {
21 r = append(r, bigZero)
22 }
23 return r
24}
25
26func PolMul(a, b []*big.Float) []*big.Float {
27 r := ArrayOfBigZeros(len(a) + len(b) - 1)
28 for i := 0; i < len(a); i++ {
29 for j := 0; j < len(b); j++ {
30 r[i+j] = new(big.Float).Add(
31 r[i+j],
32 new(big.Float).Mul(a[i], b[j]))
33 }
34 }
35 return r
36}
37
38func PolDiv(a, b []*big.Float) ([]*big.Float, []*big.Float) {
39 // https://en.wikipedia.org/wiki/Division_algorithm
40 r := ArrayOfBigZeros(len(a) - len(b) + 1)
41 rem := a
42 for len(rem) >= len(b) {
43 l := new(big.Float).Quo(rem[len(rem)-1], b[len(b)-1])
44 pos := len(rem) - len(b)
45 r[pos] = l
46 aux := ArrayOfBigZeros(pos)
47 aux1 := append(aux, l)
48 aux2 := PolSub(rem, PolMul(b, aux1))
49 rem = aux2[:len(aux2)-1]
50 }
51 return r, rem
52}
53
54func max(a, b int) int {
55 if a > b {
56 return a
57 }
58 return b
59}
60
61func PolAdd(a, b []*big.Float) []*big.Float {
62 r := ArrayOfBigZeros(max(len(a), len(b)))
63 for i := 0; i < len(a); i++ {
64 r[i] = new(big.Float).Add(r[i], a[i])
65 }
66 for i := 0; i < len(b); i++ {
67 r[i] = new(big.Float).Add(r[i], b[i])
68 }
69 return r
70}
71
72func PolSub(a, b []*big.Float) []*big.Float {
73 r := ArrayOfBigZeros(max(len(a), len(b)))
74 for i := 0; i < len(a); i++ {
75 r[i] = new(big.Float).Add(r[i], a[i])
76 }
77 for i := 0; i < len(b); i++ {
78 bneg := new(big.Float).Mul(b[i], big.NewFloat(float64(-1)))
79 r[i] = new(big.Float).Add(r[i], bneg)
80 }
81 return r
82
83}
84
85func FloatPow(a *big.Float, e int) *big.Float {
86 if e == 0 {
87 return big.NewFloat(float64(1))
88 }
89 result := new(big.Float).Copy(a)
90 for i := 0; i < e-1; i++ {
91 result = new(big.Float).Mul(result, a)
92 }
93 return result
94}
95
96func PolEval(v []*big.Float, x *big.Float) *big.Float {
97 r := big.NewFloat(float64(0))
98 for i := 0; i < len(v); i++ {
99 xi := FloatPow(x, i)
100 elem := new(big.Float).Mul(v[i], xi)
101 r = new(big.Float).Add(r, elem)
102 }
103 return r
104}
105
106func NewPolZeroAt(pointPos, totalPoints int, height *big.Float) []*big.Float {
107 fac := 1
108 for i := 1; i < totalPoints+1; i++ {
109 if i != pointPos {
110 fac = fac * (pointPos - i)
111 }
112 }
113 facBig := big.NewFloat(float64(fac))
114 hf := new(big.Float).Quo(height, facBig)
115 r := []*big.Float{hf}
116 for i := 1; i < totalPoints+1; i++ {
117 if i != pointPos {
118 ineg := big.NewFloat(float64(-i))
119 b1 := big.NewFloat(float64(1))
120 r = PolMul(r, []*big.Float{ineg, b1})
121 }
122 }
123 return r
124}
125
126func LagrangeInterpolation(v []*big.Float) []*big.Float {
127 // https://en.wikipedia.org/wiki/Lagrange_polynomial
128 var r []*big.Float
129 for i := 0; i < len(v); i++ {
130 r = PolAdd(r, NewPolZeroAt(i+1, len(v), v[i]))
131 }
132 //
133 return r
134}
135
136func R1CSToQAP(a, b, c [][]*big.Float) ([][]*big.Float, [][]*big.Float, [][]*big.Float, []*big.Float) {
137 aT := Transpose(a)
138 bT := Transpose(b)
139 cT := Transpose(c)
140 var alpha [][]*big.Float
141 for i := 0; i < len(aT); i++ {
142 alpha = append(alpha, LagrangeInterpolation(aT[i]))
143 }
144 var beta [][]*big.Float
145 for i := 0; i < len(bT); i++ {
146 beta = append(beta, LagrangeInterpolation(bT[i]))
147 }
148 var gamma [][]*big.Float
149 for i := 0; i < len(cT); i++ {
150 gamma = append(gamma, LagrangeInterpolation(cT[i]))
151 }
152 z := []*big.Float{big.NewFloat(float64(1))}
153 for i := 1; i < len(aT[0])+1; i++ {
154 ineg := big.NewFloat(float64(-i))
155 b1 := big.NewFloat(float64(1))
156 z = PolMul(z, []*big.Float{ineg, b1})
157 }
158 return alpha, beta, gamma, z
159}
160
161func SolPolynomials(r []*big.Float, ap, bp, cp [][]*big.Float) ([]*big.Float, []*big.Float, []*big.Float, []*big.Float) {
162 var alpha []*big.Float
163 for i := 0; i < len(r); i++ {
164 m := PolMul([]*big.Float{r[i]}, ap[i])
165 alpha = PolAdd(alpha, m)
166 }
167 var beta []*big.Float
168 for i := 0; i < len(r); i++ {
169 m := PolMul([]*big.Float{r[i]}, bp[i])
170 beta = PolAdd(beta, m)
171 }
172 var gamma []*big.Float
173 for i := 0; i < len(r); i++ {
174 m := PolMul([]*big.Float{r[i]}, cp[i])
175 gamma = PolAdd(gamma, m)
176 }
177
178 px := PolSub(PolMul(alpha, beta), gamma)
179 return alpha, beta, gamma, px
180}
181
182func DivisorPolinomial(px, z []*big.Float) []*big.Float {
183 quo, _ := PolDiv(px, z)
184 return quo
185}