Skip to content

Commit

Permalink
Add Polynomial::lagrange_basis
Browse files Browse the repository at this point in the history
  • Loading branch information
Denis committed Aug 11, 2021
1 parent 02d683d commit cbb90e7
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 0 deletions.
43 changes: 43 additions & 0 deletions src/cryptographic_primitives/secret_sharing/polynomial.rs
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,49 @@ impl<E: Curve> Polynomial<E> {
pub fn coefficients(&self) -> &[Scalar<E>] {
&self.coefficients
}

/// Calculates lagrange interpolation `l_j(x, xs)`
///
/// ## Panics
/// This function will panic if elements in `xs` are not pairwise distinct, or `j >= xs.len()`
///
/// ## Example
/// If you have polynomial `f` defined as `t+1` points `(x_0, y_0), ..., (x_t, y_t)` (and polynomial
/// degree is `t`), then you can, for instance, calculate `f(15)`:
///
/// ```rust
/// use curv::cryptographic_primitives::secret_sharing::Polynomial;
/// # use curv::elliptic::curves::*;
///
/// # let t = 3;
/// # let f = Polynomial::<Secp256r1>::sample_exact(t);
/// # let (x_0, x_1, x_2, x_3) = (Scalar::from(1), Scalar::from(2), Scalar::from(3), Scalar::from(4));
/// # let (y_0, y_1, y_2, y_3) = (f.evaluate(&x_0), f.evaluate(&x_1), f.evaluate(&x_2), f.evaluate(&x_3));
/// let xs = &[x_0, x_1, x_2, x_3];
/// let ys = &[y_0, y_1, y_2, y_3];
///
/// let f_15: Scalar<_> = (0..).zip(ys)
/// .map(|(j, y_j)| y_j * Polynomial::lagrange_interpolation(&Scalar::from(15), j, xs))
/// .sum();
/// assert_eq!(f_15, f.evaluate(&Scalar::from(15)));
/// ```
pub fn lagrange_interpolation(x: &Scalar<E>, j: u16, xs: &[Scalar<E>]) -> Scalar<E> {
let x_j = &xs[usize::from(j)];
let num: Scalar<E> = (0u16..)
.zip(xs)
.filter(|(m, _)| *m != j)
.map(|(_, x_m)| x - x_m)
.product();
let denum: Scalar<E> = (0u16..)
.zip(xs)
.filter(|(m, _)| *m != j)
.map(|(_, x_m)| x_j - x_m)
.product();
let denum = denum
.invert()
.expect("elements in xs are not pairwise distinct");
num * denum
}
}

/// Multiplies polynomial `f(x)` at scalar `s`, returning resulting polynomial `g(x) = s * f(x)`
Expand Down
3 changes: 3 additions & 0 deletions src/elliptic/curves/p256.rs
Original file line number Diff line number Diff line change
Expand Up @@ -180,12 +180,15 @@ impl ECScalar for Secp256r1Scalar {
}

fn add_assign(&mut self, other: &Self) {
self.purpose = "add_assign";
*self.fe += &*other.fe
}
fn mul_assign(&mut self, other: &Self) {
self.purpose = "mul_assign";
*self.fe *= &*other.fe
}
fn sub_assign(&mut self, other: &Self) {
self.purpose = "sub_assign";
*self.fe -= &*other.fe
}

Expand Down

0 comments on commit cbb90e7

Please sign in to comment.