use crate::*;
use generic_array::{ArrayLength, GenericArray};
use hybrid_array::{Array, ArraySize};
use rand_core::{CryptoRng, RngCore};
pub trait Polynomial<S: Share> {
fn create(size_hint: usize) -> Self;
fn fill(
&mut self,
intercept: &S::Value,
mut rng: impl RngCore + CryptoRng,
length: usize,
) -> VsssResult<()> {
let repr = self.coefficients_mut();
if repr.len() < length {
return Err(Error::InvalidSizeRequest);
}
*repr[0].value_mut() = intercept.clone();
for i in repr.iter_mut().take(length).skip(1) {
*i.identifier_mut() = S::Identifier::random_coefficient(&mut rng);
}
Ok(())
}
fn evaluate(&self, x: &S::Identifier, threshold: usize) -> S::Value {
let coefficients = self.coefficients();
let degree = threshold - 1;
let mut out = coefficients[degree].identifier().clone();
for i in (0..degree).rev() {
*out *= x.as_ref();
*out += coefficients[i].identifier().as_ref();
}
let mut out = S::Value::from(&out);
*out += coefficients[0].value().as_ref();
out
}
fn coefficients(&self) -> &[S];
fn coefficients_mut(&mut self) -> &mut [S];
}
impl<S: Share, const L: usize> Polynomial<S> for [S; L] {
fn create(_size_hint: usize) -> Self {
core::array::from_fn(|_| Default::default())
}
fn coefficients(&self) -> &[S] {
self
}
fn coefficients_mut(&mut self) -> &mut [S] {
self
}
}
impl<S: Share, L: ArrayLength> Polynomial<S> for GenericArray<S, L> {
fn create(_size_hint: usize) -> Self {
GenericArray::default()
}
fn coefficients(&self) -> &[S] {
self.as_ref()
}
fn coefficients_mut(&mut self) -> &mut [S] {
self.as_mut()
}
}
impl<S: Share, L: ArraySize> Polynomial<S> for Array<S, L> {
fn create(_size_hint: usize) -> Self {
Array::default()
}
fn coefficients(&self) -> &[S] {
self.as_ref()
}
fn coefficients_mut(&mut self) -> &mut [S] {
self.as_mut()
}
}
#[cfg(any(feature = "alloc", feature = "std"))]
impl<S: Share> Polynomial<S> for Vec<S> {
fn create(size_hint: usize) -> Self {
vec![Default::default(); size_hint]
}
fn coefficients(&self) -> &[S] {
self.as_ref()
}
fn coefficients_mut(&mut self) -> &mut [S] {
self.as_mut()
}
}