1use ark_ff::PrimeField;
2
3use std::ops::{Add, Mul};
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
7pub struct Monomial<F: PrimeField> {
8 pub exponent: usize,
10 pub coefficients: F,
12}
13impl<F: PrimeField> Monomial<F> {
14 pub fn new(exponent: usize, coefficients: F) -> Monomial<F> {
25 Monomial {
26 exponent,
27 coefficients,
28 }
29 }
30 pub fn default() -> Monomial<F> {
36 Monomial {
37 exponent: 0,
38 coefficients: F::zero(),
39 }
40 }
41}
42#[derive(Debug, Clone)]
44pub struct UnivariatePolynomial<F: PrimeField> {
45 monomials: Vec<Monomial<F>>,
47 pub degree: Option<u32>,
49}
50impl<F: PrimeField> UnivariatePolynomial<F> {
51 pub fn new(monomials: Vec<Monomial<F>>) -> UnivariatePolynomial<F> {
60 UnivariatePolynomial {
61 monomials,
62 degree: None,
63 }
64 }
65 pub fn default() -> UnivariatePolynomial<F> {
71 UnivariatePolynomial {
72 monomials: Vec::new(),
73 degree: None,
74 }
75 }
76
77 pub fn evaluate(&self, x: F) -> F {
87 let mut result: F = F::zero();
88 let n = self.monomials.len();
89 for i in 0..n {
90 result += self.monomials[i].coefficients
91 * F::from(x).pow(&[self.monomials[i].exponent as u64]);
92 }
93 return result;
94 }
95
96 pub fn degree(&mut self) -> Option<u32> {
102 let n = self.monomials.len();
103 if self.degree.is_none() {
104 for i in 0..n {
105 if self.monomials[i].exponent as u32 > self.degree.unwrap_or(0) {
106 self.degree = Some(self.monomials[i].exponent as u32);
107 }
108 }
109 return self.degree;
110 } else {
111 return self.degree;
112 }
113 }
114 pub fn interpolate(x: Vec<F>, y: Vec<F>) -> UnivariatePolynomial<F> {
126 let n = x.len();
127 let mut result = UnivariatePolynomial::default();
128
129 for i in 0..n {
132 let mut denominator = F::from(1);
133
134 let mut numerator = UnivariatePolynomial::new(vec![Monomial::new(0, F::one())]);
135
136 let mut a = y[i];
137 for j in 0..n {
138 if i != j {
139 let x_n = Monomial::new(1, F::one()); let x_j = Monomial::new(0, F::from(-x[j]));
141 let temp_poly = UnivariatePolynomial::new(vec![x_n, x_j]);
142
143 numerator = numerator * temp_poly;
144
145 denominator = denominator * (F::from(x[i]) - F::from(x[j]));
146 }
147 }
148
149 a /= denominator;
150
151 for monomial in &mut numerator.monomials {
152 monomial.coefficients *= F::from(a);
153 }
154
155 result = result + numerator;
156 }
157
158 result
159 }
160}
161
162impl<F: PrimeField> Mul for UnivariatePolynomial<F> {
163 type Output = UnivariatePolynomial<F>;
164 fn mul(self, p2: UnivariatePolynomial<F>) -> Self {
175 let p1: Vec<Monomial<F>> = self.monomials;
176 let p2: Vec<Monomial<F>> = p2.monomials;
177
178 let mut polynomial: Vec<Monomial<F>> = Vec::new();
179 for i in 0..p1.len() {
180 for j in 0..p2.len() {
181 polynomial.push(Monomial {
182 coefficients: p1[i].coefficients * p2[j].coefficients,
183 exponent: p1[i].exponent.wrapping_add(p2[j].exponent),
184 });
185 }
186 }
187 for i in 0..polynomial.len() {
190 let mut j = i + 1;
191 while j < polynomial.len() {
192 if polynomial[i].exponent == polynomial[j].exponent {
193 let (left, right) = polynomial.split_at_mut(j);
194 left[i].coefficients += right[0].coefficients;
195 polynomial.remove(j);
196 } else {
197 j += 1;
198 }
199 }
200 }
201 UnivariatePolynomial {
202 monomials: polynomial,
203 degree: None,
204 }
205 }
206}
207
208impl<F: PrimeField> Add for UnivariatePolynomial<F> {
209 type Output = UnivariatePolynomial<F>;
210 fn add(self, p2: UnivariatePolynomial<F>) -> Self {
221 let p1: Vec<Monomial<F>> = self.monomials;
222 let p2: Vec<Monomial<F>> = p2.monomials;
223 let mut polynomial: Vec<Monomial<F>> = Vec::new();
224 polynomial = [p1, p2].concat();
225 for i in 0..polynomial.len() {
228 let mut j = i + 1;
229 while j < polynomial.len() {
230 if polynomial[i].exponent == polynomial[j].exponent {
231 let (left, right) = polynomial.split_at_mut(j);
232 left[i].coefficients += right[0].coefficients;
233 polynomial.remove(j);
234 } else {
235 j += 1;
236 }
237 }
238 }
239 UnivariatePolynomial {
240 monomials: polynomial,
241 degree: None,
242 }
243 }
244}
245
246#[cfg(test)]
247mod tests {
248 use super::*;
249 use ark_bn254::Fq;
250
251 #[test]
252 fn test_evaluate() {
254 let default = UnivariatePolynomial::default();
255 let m1 = Monomial::new(2, Fq::from(3u32));
256 let m2 = Monomial::new(1, Fq::from(2u32));
257 let m3 = Monomial::new(0, Fq::from(5u32));
258
259 let p = UnivariatePolynomial {
260 monomials: vec![m1, m2, m3],
261 ..default
262 };
263 let result = p.evaluate(Fq::from(4));
264 assert_eq!(result, Fq::from(61u32));
265 }
266
267 #[test]
270 fn test_degree() {
271 let default = UnivariatePolynomial::<Fq>::default();
272 let m1 = Monomial::new(2, Fq::from(3u32));
273 let m2 = Monomial::new(1, Fq::from(2u32));
274
275 let mut p = UnivariatePolynomial {
276 monomials: vec![m1, m2],
277 ..default
278 };
279 let result = p.degree();
280 assert_eq!(result, Some(2));
281 }
282
283 #[test]
286 fn test_multiplication() {
287 let default = UnivariatePolynomial::default();
288 let m1 = Monomial::new(3, Fq::from(4u32));
289 let m2 = Monomial::new(2, Fq::from(3u32));
290 let m5 = Monomial::new(1, Fq::from(3u32));
291 let m3 = Monomial::new(2, Fq::from(5u32));
292 let m4 = Monomial::new(1, Fq::from(7u32));
293
294 let p1 = UnivariatePolynomial {
295 monomials: vec![m1, m2, m5],
296 ..default
297 };
298 let p2 = UnivariatePolynomial {
299 monomials: vec![m3, m4],
300 ..default
301 };
302 let result = p1 * p2;
303 assert_eq!(result.monomials[0].coefficients, Fq::from(20u32));
304 assert_eq!(result.monomials[1].coefficients, Fq::from(43u32));
305 assert_eq!(result.monomials[2].coefficients, Fq::from(36u32));
306 assert_eq!(result.monomials[3].coefficients, Fq::from(21u32));
307 assert_eq!(result.monomials[0].exponent, 5);
308 assert_eq!(result.monomials[1].exponent, 4);
309 assert_eq!(result.monomials[2].exponent, 3);
310 assert_eq!(result.monomials[3].exponent, 2);
311 }
312
313 #[test]
315 fn test_interpolate() {
316 let x = vec![Fq::from(1), Fq::from(2), Fq::from(3)];
317 let y = vec![Fq::from(1), Fq::from(4), Fq::from(9)];
318 let result = UnivariatePolynomial::<Fq>::interpolate(x, y);
319 assert_eq!(result.monomials[0].coefficients, Fq::from(1u32));
320 assert_eq!(result.monomials[0].exponent, 2);
321 }
322}