202 lines
6.1 KiB
Java
202 lines
6.1 KiB
Java
package ShamirSecretSharing;
|
|
|
|
import org.bouncycastle.util.Arrays;
|
|
import org.factcenter.qilin.primitives.concrete.ECGroup;
|
|
import org.factcenter.qilin.util.Pair;
|
|
|
|
import java.math.BigInteger;
|
|
|
|
/**
|
|
* Created by Tzlil on 1/27/2016.
|
|
*/
|
|
public class Polynomial implements Comparable<Polynomial> {
|
|
protected static final Polynomial ZERO = new Polynomial(new BigInteger[]{BigInteger.ZERO}); // neutral for add
|
|
protected static final Polynomial ONE = new Polynomial(new BigInteger[]{BigInteger.ONE}); // neutral for mul
|
|
private final int degree;
|
|
private final BigInteger[] coefficients;
|
|
|
|
/**
|
|
* constructor
|
|
* @param coefficients
|
|
* degree set as max index such that coefficients[degree] not equals zero
|
|
*/
|
|
public Polynomial(BigInteger[] coefficients) {
|
|
int d = coefficients.length - 1;
|
|
while (d > 0 && coefficients[d].equals(BigInteger.ZERO)){
|
|
d--;
|
|
}
|
|
this.degree = d;
|
|
this.coefficients = coefficients;
|
|
}
|
|
|
|
|
|
@Override
|
|
public int compareTo(Polynomial other) {
|
|
if (this.degree != other.degree)
|
|
return this.degree - other.degree;
|
|
int compare;
|
|
for (int i = degree; i >= degree ; i--){
|
|
compare = this.coefficients[i].compareTo(other.coefficients[i]);
|
|
if (compare != 0){
|
|
return compare;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
@Override
|
|
public String toString() {
|
|
return "Polynomial{" +
|
|
"degree=" + degree +
|
|
", coefficients=" + java.util.Arrays.toString(coefficients) +
|
|
'}';
|
|
}
|
|
|
|
|
|
/**
|
|
* @param x
|
|
* @return sum of coefficients[i] * (x ^ i)
|
|
*/
|
|
public BigInteger image(BigInteger x){
|
|
BigInteger result = BigInteger.ZERO;
|
|
BigInteger power = BigInteger.ONE;
|
|
for(int i = 0 ; i <= degree ; i++){
|
|
result = result.add(coefficients[i].multiply(power));
|
|
power = power.multiply(x);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* @param points
|
|
* @return polynomial of minimal degree which goes through all points
|
|
*/
|
|
public static Polynomial interpolation(Point[] points){
|
|
LagrangePolynomial[] l = LagrangePolynomial.lagrangePolynomials(points);
|
|
|
|
// product = product of l[i].divisor
|
|
BigInteger product = BigInteger.ONE;
|
|
for (int i = 0; i < l.length;i++){
|
|
product = product.multiply(l[i].divisor);
|
|
}
|
|
|
|
// factor[i] = product divided by l[i].divisor = product of l[j].divisor s.t j!=i
|
|
BigInteger[] factors = new BigInteger[l.length];
|
|
for (int i = 0; i < l.length;i++){
|
|
factors[i] = product.divide(l[i].divisor);
|
|
}
|
|
int degree = l[0].polynomial.degree;
|
|
|
|
// coefficients[j] = (sum of l[i].image * factor[i] * l[i].coefficients[j] s.t i!=j) divide by product =
|
|
// = sum of l[i].image * l[i].coefficients[j] / l[i].divisor s.t i!=j
|
|
BigInteger[] coefficients = new BigInteger[degree + 1];
|
|
for (int j = 0; j < coefficients.length;j++){
|
|
coefficients[j] = BigInteger.ZERO;
|
|
for (int i = 0; i < l.length; i++){
|
|
coefficients[j] = coefficients[j].add(l[i].image.multiply(factors[i]).multiply(l[i].polynomial.coefficients[j]));
|
|
}
|
|
coefficients[j] = coefficients[j].divide(product);
|
|
}
|
|
return new Polynomial(coefficients);
|
|
}
|
|
|
|
/**
|
|
* @param other
|
|
* @return new Polynomial of degree max(this degree,other degree) s.t for all x in Z
|
|
* new.image(x) = this.image(x) + other.image(x)
|
|
*/
|
|
public Polynomial add(Polynomial other){
|
|
Polynomial bigger,smaller;
|
|
if(this.degree < other.degree){
|
|
bigger = other;
|
|
smaller = this;
|
|
}else{
|
|
bigger = this;
|
|
smaller = other;
|
|
}
|
|
BigInteger[] coefficients = bigger.getCoefficients();
|
|
|
|
for (int i = 0; i <= smaller.degree ; i++){
|
|
coefficients[i] = smaller.coefficients[i].add(bigger.coefficients[i]);
|
|
}
|
|
return new Polynomial(coefficients);
|
|
}
|
|
|
|
/**
|
|
* @param constant
|
|
* @return new Polynomial of degree this.degree s.t for all x in Z
|
|
* new.image(x) = constant * this.image(x)
|
|
*/
|
|
public Polynomial mul(BigInteger constant){
|
|
|
|
BigInteger[] coefficients = this.getCoefficients();
|
|
|
|
for (int i = 0; i <= this.degree ; i++){
|
|
coefficients[i] = constant.multiply(coefficients[i]);
|
|
}
|
|
return new Polynomial(coefficients);
|
|
}
|
|
|
|
/**
|
|
* @param other
|
|
* @return new Polynomial of degree this degree + other degree + 1 s.t for all x in Z
|
|
* new.image(x) = this.image(x) * other.image(x)
|
|
*/
|
|
public Polynomial mul(Polynomial other){
|
|
|
|
BigInteger[] coefficients = new BigInteger[this.degree + other.degree + 1];
|
|
java.util.Arrays.fill(coefficients,BigInteger.ZERO);
|
|
|
|
for (int i = 0; i <= this.degree ; i++){
|
|
for (int j = 0; j <= other.degree; j++){
|
|
coefficients[i+j] = coefficients[i+j].add(this.coefficients[i].multiply(other.coefficients[j]));
|
|
}
|
|
}
|
|
return new Polynomial(coefficients);
|
|
}
|
|
|
|
|
|
/** getter
|
|
* @return copy of coefficients
|
|
*/
|
|
public BigInteger[] getCoefficients() {
|
|
return Arrays.clone(coefficients);
|
|
}
|
|
|
|
/** getter
|
|
* @return degree
|
|
*/
|
|
public int getDegree() {
|
|
return degree;
|
|
}
|
|
|
|
/**
|
|
* inner class
|
|
* container for (x,y) x from range and y from image of polynomial
|
|
*/
|
|
public static class Point{
|
|
public final BigInteger x;
|
|
public final BigInteger y;
|
|
|
|
/**
|
|
* constructor
|
|
* @param x
|
|
* @param polynomial y = polynomial.image(x)
|
|
*/
|
|
public Point(BigInteger x, Polynomial polynomial) {
|
|
this.x = x;
|
|
this.y = polynomial.image(x);
|
|
}
|
|
|
|
/**
|
|
* copy constructor
|
|
* @param point
|
|
*/
|
|
public Point(Point point) {
|
|
this.x = point.x;
|
|
this.y = point.y;
|
|
}
|
|
}
|
|
|
|
}
|