mirror of
https://github.com/arnaucube/kzg-commitments-study.git
synced 2026-02-06 19:16:44 +01:00
Add Lagrange Interpolation & Zero polynomial
This commit is contained in:
@@ -69,6 +69,12 @@ func compareBigIntArray(a, b []*big.Int) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
//nolint:deadcode,unused
|
||||
func checkArrayOfZeroes(a []*big.Int) bool {
|
||||
z := arrayOfZeroes(len(a))
|
||||
return compareBigIntArray(a, z)
|
||||
}
|
||||
|
||||
func fAdd(a, b *big.Int) *big.Int {
|
||||
ab := new(big.Int).Add(a, b)
|
||||
return ab.Mod(ab, R)
|
||||
@@ -89,7 +95,6 @@ func fDiv(a, b *big.Int) *big.Int {
|
||||
return new(big.Int).Mod(ab, R)
|
||||
}
|
||||
|
||||
//nolint:unused,deadcode // TODO check
|
||||
func fNeg(a *big.Int) *big.Int {
|
||||
return new(big.Int).Mod(new(big.Int).Neg(a), R)
|
||||
}
|
||||
@@ -170,6 +175,19 @@ func polynomialDiv(a, b []*big.Int) ([]*big.Int, []*big.Int) {
|
||||
return r, rem
|
||||
}
|
||||
|
||||
func polynomialMulByConstant(a []*big.Int, c *big.Int) []*big.Int {
|
||||
for i := 0; i < len(a); i++ {
|
||||
a[i] = fMul(a[i], c)
|
||||
}
|
||||
return a
|
||||
}
|
||||
func polynomialDivByConstant(a []*big.Int, c *big.Int) []*big.Int {
|
||||
for i := 0; i < len(a); i++ {
|
||||
a[i] = fDiv(a[i], c)
|
||||
}
|
||||
return a
|
||||
}
|
||||
|
||||
// polynomialEval evaluates the polinomial over the Finite Field at the given value x
|
||||
func polynomialEval(p []*big.Int, x *big.Int) *big.Int {
|
||||
r := big.NewInt(int64(0))
|
||||
@@ -202,6 +220,16 @@ func newPolZeroAt(pointPos, totalPoints int, height *big.Int) []*big.Int {
|
||||
return r
|
||||
}
|
||||
|
||||
// zeroPolynomial returns the zero polynomial:
|
||||
// z(x) = (x - z_0) (x - z_1) ... (x - z_{k-1})
|
||||
func zeroPolynomial(zs []*big.Int) []*big.Int {
|
||||
z := []*big.Int{fNeg(zs[0]), big.NewInt(1)}
|
||||
for i := 1; i < len(zs); i++ {
|
||||
z = polynomialMul(z, []*big.Int{fNeg(zs[i]), big.NewInt(1)})
|
||||
}
|
||||
return z
|
||||
}
|
||||
|
||||
var sNums = map[string]string{
|
||||
"0": "⁰",
|
||||
"1": "¹",
|
||||
@@ -237,4 +265,40 @@ func PolynomialToString(p []*big.Int) string {
|
||||
return s
|
||||
}
|
||||
|
||||
// LagrangeInterpolation implements the Lagrange interpolation:
|
||||
// https://en.wikipedia.org/wiki/Lagrange_polynomial
|
||||
func LagrangeInterpolation(x, y []*big.Int) ([]*big.Int, error) {
|
||||
// p(x) will be the interpoled polynomial
|
||||
// var p []*big.Int
|
||||
if len(x) != len(y) {
|
||||
return nil, fmt.Errorf("len(x)!=len(y): %d, %d", len(x), len(y))
|
||||
}
|
||||
p := arrayOfZeroes(len(x))
|
||||
k := len(x)
|
||||
|
||||
for j := 0; j < k; j++ {
|
||||
// jPol is the Lagrange basis polynomial for each point
|
||||
var jPol []*big.Int
|
||||
for m := 0; m < k; m++ {
|
||||
// if x[m] == x[j] {
|
||||
if m == j {
|
||||
continue
|
||||
}
|
||||
// numerator & denominator of the current iteration
|
||||
num := []*big.Int{fNeg(x[m]), big.NewInt(1)} // (x^1 - x_m)
|
||||
den := fSub(x[j], x[m]) // x_j-x_m
|
||||
mPol := polynomialDivByConstant(num, den)
|
||||
if len(jPol) == 0 {
|
||||
// first j iteration
|
||||
jPol = mPol
|
||||
continue
|
||||
}
|
||||
jPol = polynomialMul(jPol, mPol)
|
||||
}
|
||||
p = polynomialAdd(p, polynomialMulByConstant(jPol, y[j]))
|
||||
}
|
||||
|
||||
return p, nil
|
||||
}
|
||||
|
||||
// TODO add method to 'clean' the polynomial, to remove right-zeroes
|
||||
|
||||
@@ -80,6 +80,21 @@ func TestPolynomial(t *testing.T) {
|
||||
assert.Equal(t, polynomialEval(o, big.NewInt(3)), b4)
|
||||
o = newPolZeroAt(2, 4, b3)
|
||||
assert.Equal(t, polynomialEval(o, big.NewInt(2)), b3)
|
||||
|
||||
// polynomialEval
|
||||
// p(x) = x^3 + x + 5
|
||||
p := []*big.Int{
|
||||
big.NewInt(5),
|
||||
big.NewInt(1), // x^1
|
||||
big.NewInt(0), // x^2
|
||||
big.NewInt(1), // x^3
|
||||
}
|
||||
assert.Equal(t, "1x³ + 1x¹ + 5", PolynomialToString(p))
|
||||
assert.Equal(t, "35", polynomialEval(p, big.NewInt(3)).String())
|
||||
assert.Equal(t, "1015", polynomialEval(p, big.NewInt(10)).String())
|
||||
assert.Equal(t, "16777477", polynomialEval(p, big.NewInt(256)).String())
|
||||
assert.Equal(t, "125055", polynomialEval(p, big.NewInt(50)).String())
|
||||
assert.Equal(t, "7", polynomialEval(p, big.NewInt(1)).String())
|
||||
}
|
||||
|
||||
func BenchmarkArithmetic(b *testing.B) {
|
||||
@@ -109,3 +124,42 @@ func BenchmarkArithmetic(b *testing.B) {
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestLagrangeInterpolation(t *testing.T) {
|
||||
x0 := big.NewInt(3)
|
||||
y0 := big.NewInt(35)
|
||||
x1 := big.NewInt(10)
|
||||
y1 := big.NewInt(1015)
|
||||
x2 := big.NewInt(256)
|
||||
y2 := big.NewInt(16777477)
|
||||
x3 := big.NewInt(50)
|
||||
y3 := big.NewInt(125055)
|
||||
|
||||
xs := []*big.Int{x0, x1, x2, x3}
|
||||
ys := []*big.Int{y0, y1, y2, y3}
|
||||
|
||||
p, err := LagrangeInterpolation(xs, ys)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, "1x³ + 1x¹ + 5", PolynomialToString(p))
|
||||
|
||||
assert.Equal(t, y0, polynomialEval(p, x0))
|
||||
assert.Equal(t, y1, polynomialEval(p, x1))
|
||||
assert.Equal(t, y2, polynomialEval(p, x2))
|
||||
}
|
||||
|
||||
func TestZeroPolynomial(t *testing.T) {
|
||||
x0 := big.NewInt(1)
|
||||
x1 := big.NewInt(40)
|
||||
x2 := big.NewInt(512)
|
||||
xs := []*big.Int{x0, x1, x2}
|
||||
|
||||
z := zeroPolynomial(xs)
|
||||
assert.Equal(t, "1x³ "+
|
||||
"+ 21888242871839275222246405745257275088548364400416034343698204186575808495064x² "+
|
||||
"+ 21032x¹ + 21888242871839275222246405745257275088548364400416034343698204186575808475137",
|
||||
PolynomialToString(z))
|
||||
|
||||
assert.Equal(t, "0", polynomialEval(z, x0).String())
|
||||
assert.Equal(t, "0", polynomialEval(z, x1).String())
|
||||
assert.Equal(t, "0", polynomialEval(z, x2).String())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user