package r1csqapFloat
|
|
|
|
import "math/big"
|
|
|
|
func Transpose(matrix [][]*big.Float) [][]*big.Float {
|
|
var r [][]*big.Float
|
|
for i := 0; i < len(matrix[0]); i++ {
|
|
var row []*big.Float
|
|
for j := 0; j < len(matrix); j++ {
|
|
row = append(row, matrix[j][i])
|
|
}
|
|
r = append(r, row)
|
|
}
|
|
return r
|
|
}
|
|
|
|
func ArrayOfBigZeros(num int) []*big.Float {
|
|
bigZero := big.NewFloat(float64(0))
|
|
var r []*big.Float
|
|
for i := 0; i < num; i++ {
|
|
r = append(r, bigZero)
|
|
}
|
|
return r
|
|
}
|
|
|
|
func PolMul(a, b []*big.Float) []*big.Float {
|
|
r := ArrayOfBigZeros(len(a) + len(b) - 1)
|
|
for i := 0; i < len(a); i++ {
|
|
for j := 0; j < len(b); j++ {
|
|
r[i+j] = new(big.Float).Add(
|
|
r[i+j],
|
|
new(big.Float).Mul(a[i], b[j]))
|
|
}
|
|
}
|
|
return r
|
|
}
|
|
|
|
func PolDiv(a, b []*big.Float) ([]*big.Float, []*big.Float) {
|
|
// https://en.wikipedia.org/wiki/Division_algorithm
|
|
r := ArrayOfBigZeros(len(a) - len(b) + 1)
|
|
rem := a
|
|
for len(rem) >= len(b) {
|
|
l := new(big.Float).Quo(rem[len(rem)-1], b[len(b)-1])
|
|
pos := len(rem) - len(b)
|
|
r[pos] = l
|
|
aux := ArrayOfBigZeros(pos)
|
|
aux1 := append(aux, l)
|
|
aux2 := PolSub(rem, PolMul(b, aux1))
|
|
rem = aux2[:len(aux2)-1]
|
|
}
|
|
return r, rem
|
|
}
|
|
|
|
func max(a, b int) int {
|
|
if a > b {
|
|
return a
|
|
}
|
|
return b
|
|
}
|
|
|
|
func PolAdd(a, b []*big.Float) []*big.Float {
|
|
r := ArrayOfBigZeros(max(len(a), len(b)))
|
|
for i := 0; i < len(a); i++ {
|
|
r[i] = new(big.Float).Add(r[i], a[i])
|
|
}
|
|
for i := 0; i < len(b); i++ {
|
|
r[i] = new(big.Float).Add(r[i], b[i])
|
|
}
|
|
return r
|
|
}
|
|
|
|
func PolSub(a, b []*big.Float) []*big.Float {
|
|
r := ArrayOfBigZeros(max(len(a), len(b)))
|
|
for i := 0; i < len(a); i++ {
|
|
r[i] = new(big.Float).Add(r[i], a[i])
|
|
}
|
|
for i := 0; i < len(b); i++ {
|
|
bneg := new(big.Float).Mul(b[i], big.NewFloat(float64(-1)))
|
|
r[i] = new(big.Float).Add(r[i], bneg)
|
|
}
|
|
return r
|
|
|
|
}
|
|
|
|
func FloatPow(a *big.Float, e int) *big.Float {
|
|
if e == 0 {
|
|
return big.NewFloat(float64(1))
|
|
}
|
|
result := new(big.Float).Copy(a)
|
|
for i := 0; i < e-1; i++ {
|
|
result = new(big.Float).Mul(result, a)
|
|
}
|
|
return result
|
|
}
|
|
|
|
func PolEval(v []*big.Float, x *big.Float) *big.Float {
|
|
r := big.NewFloat(float64(0))
|
|
for i := 0; i < len(v); i++ {
|
|
xi := FloatPow(x, i)
|
|
elem := new(big.Float).Mul(v[i], xi)
|
|
r = new(big.Float).Add(r, elem)
|
|
}
|
|
return r
|
|
}
|
|
|
|
func NewPolZeroAt(pointPos, totalPoints int, height *big.Float) []*big.Float {
|
|
fac := 1
|
|
for i := 1; i < totalPoints+1; i++ {
|
|
if i != pointPos {
|
|
fac = fac * (pointPos - i)
|
|
}
|
|
}
|
|
facBig := big.NewFloat(float64(fac))
|
|
hf := new(big.Float).Quo(height, facBig)
|
|
r := []*big.Float{hf}
|
|
for i := 1; i < totalPoints+1; i++ {
|
|
if i != pointPos {
|
|
ineg := big.NewFloat(float64(-i))
|
|
b1 := big.NewFloat(float64(1))
|
|
r = PolMul(r, []*big.Float{ineg, b1})
|
|
}
|
|
}
|
|
return r
|
|
}
|
|
|
|
func LagrangeInterpolation(v []*big.Float) []*big.Float {
|
|
// https://en.wikipedia.org/wiki/Lagrange_polynomial
|
|
var r []*big.Float
|
|
for i := 0; i < len(v); i++ {
|
|
r = PolAdd(r, NewPolZeroAt(i+1, len(v), v[i]))
|
|
}
|
|
//
|
|
return r
|
|
}
|
|
|
|
func R1CSToQAP(a, b, c [][]*big.Float) ([][]*big.Float, [][]*big.Float, [][]*big.Float, []*big.Float) {
|
|
aT := Transpose(a)
|
|
bT := Transpose(b)
|
|
cT := Transpose(c)
|
|
var alphas [][]*big.Float
|
|
for i := 0; i < len(aT); i++ {
|
|
alphas = append(alphas, LagrangeInterpolation(aT[i]))
|
|
}
|
|
var betas [][]*big.Float
|
|
for i := 0; i < len(bT); i++ {
|
|
betas = append(betas, LagrangeInterpolation(bT[i]))
|
|
}
|
|
var gammas [][]*big.Float
|
|
for i := 0; i < len(cT); i++ {
|
|
gammas = append(gammas, LagrangeInterpolation(cT[i]))
|
|
}
|
|
z := []*big.Float{big.NewFloat(float64(1))}
|
|
for i := 1; i < len(aT[0])+1; i++ {
|
|
ineg := big.NewFloat(float64(-i))
|
|
b1 := big.NewFloat(float64(1))
|
|
z = PolMul(z, []*big.Float{ineg, b1})
|
|
}
|
|
return alphas, betas, gammas, z
|
|
}
|
|
|
|
func CombinePolynomials(r []*big.Float, ap, bp, cp [][]*big.Float) ([]*big.Float, []*big.Float, []*big.Float, []*big.Float) {
|
|
var alpha []*big.Float
|
|
for i := 0; i < len(r); i++ {
|
|
m := PolMul([]*big.Float{r[i]}, ap[i])
|
|
alpha = PolAdd(alpha, m)
|
|
}
|
|
var beta []*big.Float
|
|
for i := 0; i < len(r); i++ {
|
|
m := PolMul([]*big.Float{r[i]}, bp[i])
|
|
beta = PolAdd(beta, m)
|
|
}
|
|
var gamma []*big.Float
|
|
for i := 0; i < len(r); i++ {
|
|
m := PolMul([]*big.Float{r[i]}, cp[i])
|
|
gamma = PolAdd(gamma, m)
|
|
}
|
|
|
|
px := PolSub(PolMul(alpha, beta), gamma)
|
|
return alpha, beta, gamma, px
|
|
}
|
|
|
|
func DivisorPolinomial(px, z []*big.Float) []*big.Float {
|
|
quo, _ := PolDiv(px, z)
|
|
return quo
|
|
}
|