ark-r1cs-std/src/poly/polynomial/univariate/dense.rs
src/poly/polynomial/univariate/dense.rsRaw
1use ark_ff::PrimeField;
2use ark_relations::r1cs::SynthesisError;
3
4use crate::fields::fp::FpVar;
5use crate::fields::FieldVar;
6use ark_std::vec::Vec;
7
8/// Stores a polynomial in coefficient form, where coeffcient is represented by a list of `Fpvar<F>`.
9pub struct DensePolynomialVar<F: PrimeField> {
10 /// The coefficient of `x^i` is stored at location `i` in `self.coeffs`.
11 pub coeffs: Vec<FpVar<F>>,
12}
13
14impl<F: PrimeField> DensePolynomialVar<F> {
15 /// Constructs a new polynomial from a list of coefficients.
16 pub fn from_coefficients_slice(coeffs: &[FpVar<F>]) -> Self {
17 Self::from_coefficients_vec(coeffs.to_vec())
18 }
19
20 /// Constructs a new polynomial from a list of coefficients.
21 pub fn from_coefficients_vec(coeffs: Vec<FpVar<F>>) -> Self {
22 Self { coeffs }
23 }
24
25 /// Evaluates `self` at the given `point` and just gives you the gadget for the result.
26 /// Caution for use in holographic lincheck: The output has 2 entries in one matrix
27 pub fn evaluate(&self, point: &FpVar<F>) -> Result<FpVar<F>, SynthesisError> {
28 let mut result: FpVar<F> = FpVar::zero();
29 // current power of point
30 let mut curr_pow_x: FpVar<F> = FpVar::one();
31 for i in 0..self.coeffs.len() {
32 let term = &curr_pow_x * &self.coeffs[i];
33 result += &term;
34 curr_pow_x *= point;
35 }
36
37 Ok(result)
38 }
39}
40
41#[cfg(test)]
42mod tests {
43 use crate::alloc::AllocVar;
44 use crate::fields::fp::FpVar;
45 use crate::poly::polynomial::univariate::dense::DensePolynomialVar;
46 use crate::R1CSVar;
47 use ark_poly::polynomial::univariate::DensePolynomial;
48 use ark_poly::{Polynomial, UVPolynomial};
49 use ark_relations::r1cs::ConstraintSystem;
50 use ark_std::vec::Vec;
51 use ark_std::{test_rng, UniformRand};
52 use ark_test_curves::bls12_381::Fr;
53
54 #[test]
55 fn test_evaluate() {
56 let mut rng = test_rng();
57 for _ in 0..100 {
58 let cs = ConstraintSystem::new_ref();
59 let poly: DensePolynomial<Fr> = DensePolynomial::rand(10, &mut rng);
60 let poly_var = {
61 let coeff: Vec<_> = poly
62 .coeffs
63 .iter()
64 .map(|&x| FpVar::new_witness(ns!(cs, "coeff"), || Ok(x)).unwrap())
65 .collect();
66 DensePolynomialVar::from_coefficients_vec(coeff)
67 };
68 let point = Fr::rand(&mut rng);
69 let point_var = FpVar::new_witness(ns!(cs, "point"), || Ok(point)).unwrap();
70
71 let expected = poly.evaluate(&point);
72 let actual = poly_var.evaluate(&point_var).unwrap();
73
74 assert_eq!(actual.value().unwrap(), expected);
75 assert!(cs.is_satisfied().unwrap());
76 }
77 }
78}