1use crate::MVPoly;
19use ark_ff::PrimeField;
20use rand::{seq::SliceRandom, Rng};
21use std::ops::Neg;
22
23pub fn test_mul_by_one<F: PrimeField, const N: usize, const D: usize, T: MVPoly<F, N, D>>() {
24 let mut rng = o1_utils::tests::make_test_rng(None);
25 let p1 = unsafe { T::random(&mut rng, None) };
26 let one = T::one();
27 let p2 = p1.clone() * one.clone();
28 assert_eq!(p1.clone(), p2);
29 let p3 = one * p1.clone();
30 assert_eq!(p1.clone(), p3);
31}
32
33pub fn test_mul_by_zero<F: PrimeField, const N: usize, const D: usize, T: MVPoly<F, N, D>>() {
34 let mut rng = o1_utils::tests::make_test_rng(None);
35 let p1 = unsafe { T::random(&mut rng, None) };
36 let zero = T::zero();
37 let p2 = p1.clone() * zero.clone();
38 assert_eq!(zero, p2);
39 let p3 = zero.clone() * p1.clone();
40 assert_eq!(zero.clone(), p3);
41}
42
43pub fn test_add_zero<F: PrimeField, const N: usize, const D: usize, T: MVPoly<F, N, D>>() {
44 let mut rng = o1_utils::tests::make_test_rng(None);
45 let p1 = unsafe { T::random(&mut rng, None) };
46 let zero = T::zero();
47 let p2 = p1.clone() + zero.clone();
48 assert_eq!(p1.clone(), p2);
49 let p3 = zero.clone() + p1.clone();
50 assert_eq!(p1.clone(), p3);
51}
52
53pub fn test_double_is_add_twice<
54 F: PrimeField,
55 const N: usize,
56 const D: usize,
57 T: MVPoly<F, N, D>,
58>() {
59 let mut rng = o1_utils::tests::make_test_rng(None);
60 let p1 = unsafe { T::random(&mut rng, None) };
61 let p2 = p1.clone() + p1.clone();
62 let p3 = p1.clone().double();
63 assert_eq!(p2, p3);
64}
65
66pub fn test_sub_zero<F: PrimeField, const N: usize, const D: usize, T: MVPoly<F, N, D>>() {
67 let mut rng = o1_utils::tests::make_test_rng(None);
68 let p1 = unsafe { T::random(&mut rng, None) };
69 let zero = T::zero();
70 let p2 = p1.clone() - zero.clone();
71 assert_eq!(p1.clone(), p2);
72}
73
74pub fn test_neg<F: PrimeField, const N: usize, const D: usize, T: MVPoly<F, N, D>>() {
75 let mut rng = o1_utils::tests::make_test_rng(None);
76 let p1 = unsafe { T::random(&mut rng, None) };
77 let p2 = -p1.clone();
78 let sum = p1.clone() + p2.clone();
80 assert_eq!(sum, T::zero());
81 let p3 = -p2;
83 assert_eq!(p1, p3);
84 let zero = T::zero();
86 let neg_zero = -zero.clone();
87 assert_eq!(zero, neg_zero);
88}
89
90pub fn test_eval_pbt_add<F: PrimeField, const N: usize, const D: usize, T: MVPoly<F, N, D>>()
91where
92 for<'a> &'a T: std::ops::Add<T, Output = T> + std::ops::Add<&'a T, Output = T>,
93{
94 let mut rng = o1_utils::tests::make_test_rng(None);
95 let random_evaluation: [F; N] = std::array::from_fn(|_| F::rand(&mut rng));
96 let p1 = unsafe { T::random(&mut rng, None) };
97 let p2 = unsafe { T::random(&mut rng, None) };
98 let eval_p1 = p1.eval(&random_evaluation);
99 let eval_p2 = p2.eval(&random_evaluation);
100 {
101 let p3 = p1.clone() + p2.clone();
102 let eval_p3 = p3.eval(&random_evaluation);
103 assert_eq!(eval_p3, eval_p1 + eval_p2);
104 }
105 {
106 let p3 = p1.clone() + &p2;
107 let eval_p3 = p3.eval(&random_evaluation);
108 assert_eq!(eval_p3, eval_p1 + eval_p2);
109 }
110 {
111 let p3 = &p1 + p2.clone();
112 let eval_p3 = p3.eval(&random_evaluation);
113 assert_eq!(eval_p3, eval_p1 + eval_p2);
114 }
115 {
116 let p3 = &p1 + &p2;
117 let eval_p3 = p3.eval(&random_evaluation);
118 assert_eq!(eval_p3, eval_p1 + eval_p2);
119 }
120}
121
122pub fn test_eval_pbt_sub<F: PrimeField, const N: usize, const D: usize, T: MVPoly<F, N, D>>()
123where
124 for<'a> &'a T: std::ops::Sub<T, Output = T> + std::ops::Sub<&'a T, Output = T>,
125{
126 let mut rng = o1_utils::tests::make_test_rng(None);
127 let random_evaluation: [F; N] = std::array::from_fn(|_| F::rand(&mut rng));
128 let p1 = unsafe { T::random(&mut rng, None) };
129 let p2 = unsafe { T::random(&mut rng, None) };
130 let eval_p1 = p1.eval(&random_evaluation);
131 let eval_p2 = p2.eval(&random_evaluation);
132 {
133 let p3 = p1.clone() - p2.clone();
134 let eval_p3 = p3.eval(&random_evaluation);
135 assert_eq!(eval_p3, eval_p1 - eval_p2);
136 }
137 {
138 let p3 = p1.clone() - &p2;
139 let eval_p3 = p3.eval(&random_evaluation);
140 assert_eq!(eval_p3, eval_p1 - eval_p2);
141 }
142 {
143 let p3 = &p1 - p2.clone();
144 let eval_p3 = p3.eval(&random_evaluation);
145 assert_eq!(eval_p3, eval_p1 - eval_p2);
146 }
147 {
148 let p3 = &p1 - &p2;
149 let eval_p3 = p3.eval(&random_evaluation);
150 assert_eq!(eval_p3, eval_p1 - eval_p2);
151 }
152}
153
154pub fn test_eval_pbt_mul_by_scalar<
155 F: PrimeField,
156 const N: usize,
157 const D: usize,
158 T: MVPoly<F, N, D>,
159>() {
160 let mut rng = o1_utils::tests::make_test_rng(None);
161 let random_evaluation: [F; N] = std::array::from_fn(|_| F::rand(&mut rng));
162 let p1 = unsafe { T::random(&mut rng, None) };
163 let c = F::rand(&mut rng);
164 let p2 = p1.clone() * T::from(c);
165 let eval_p1 = p1.eval(&random_evaluation);
166 let eval_p2 = p2.eval(&random_evaluation);
167 assert_eq!(eval_p2, eval_p1 * c);
168}
169
170pub fn test_eval_pbt_neg<F: PrimeField, const N: usize, const D: usize, T: MVPoly<F, N, D>>() {
171 let mut rng = o1_utils::tests::make_test_rng(None);
172 let random_evaluation: [F; N] = std::array::from_fn(|_| F::rand(&mut rng));
173 let p1 = unsafe { T::random(&mut rng, None) };
174 let p2 = -p1.clone();
175 let eval_p1 = p1.eval(&random_evaluation);
176 let eval_p2 = p2.eval(&random_evaluation);
177 assert_eq!(eval_p2, -eval_p1);
178}
179
180pub fn test_neg_ref<F: PrimeField, const N: usize, const D: usize, T: MVPoly<F, N, D>>()
181where
182 for<'a> &'a T: Neg<Output = T>,
183{
184 let mut rng = o1_utils::tests::make_test_rng(None);
185 let p1 = unsafe { T::random(&mut rng, None) };
186 let p2 = -&p1;
187 let sum = p1.clone() + p2.clone();
189 assert_eq!(sum, T::zero());
190 let p3 = -&p2;
192 assert_eq!(p1, p3);
193}
194
195pub fn test_mul_by_scalar<F: PrimeField, const N: usize, const D: usize, T: MVPoly<F, N, D>>() {
196 let mut rng = o1_utils::tests::make_test_rng(None);
197 let p1 = unsafe { T::random(&mut rng, None) };
198 let mut p2 = T::zero();
199 let c = F::rand(&mut rng);
200 p2.modify_monomial([0; N], c);
201 assert_eq!(p2 * p1.clone(), p1.clone().mul_by_scalar(c));
202}
203
204pub fn test_mul_by_scalar_with_zero<
205 F: PrimeField,
206 const N: usize,
207 const D: usize,
208 T: MVPoly<F, N, D>,
209>() {
210 let mut rng = o1_utils::tests::make_test_rng(None);
211 let p1 = unsafe { T::random(&mut rng, None) };
212 let c = F::zero();
213 assert_eq!(p1.mul_by_scalar(c), T::zero());
214}
215
216pub fn test_mul_by_scalar_with_one<
217 F: PrimeField,
218 const N: usize,
219 const D: usize,
220 T: MVPoly<F, N, D>,
221>() {
222 let mut rng = o1_utils::tests::make_test_rng(None);
223 let p1 = unsafe { T::random(&mut rng, None) };
224 let c = F::one();
225 assert_eq!(p1.mul_by_scalar(c), p1);
226}
227
228pub fn test_evaluation_zero_polynomial<
229 F: PrimeField,
230 const N: usize,
231 const D: usize,
232 T: MVPoly<F, N, D>,
233>() {
234 let mut rng = o1_utils::tests::make_test_rng(None);
235 let random_evaluation: [F; N] = std::array::from_fn(|_| F::rand(&mut rng));
236 let zero = T::zero();
237 let evaluation = zero.eval(&random_evaluation);
238 assert_eq!(evaluation, F::zero());
239}
240
241pub fn test_evaluation_constant_polynomial<
242 F: PrimeField,
243 const N: usize,
244 const D: usize,
245 T: MVPoly<F, N, D>,
246>() {
247 let mut rng = o1_utils::tests::make_test_rng(None);
248 let random_evaluation: [F; N] = std::array::from_fn(|_| F::rand(&mut rng));
249 let cst = F::rand(&mut rng);
250 let poly = T::from(cst);
251 let evaluation = poly.eval(&random_evaluation);
252 assert_eq!(evaluation, cst);
253}
254
255pub fn test_degree_constant<F: PrimeField, const N: usize, const D: usize, T: MVPoly<F, N, D>>() {
256 let mut rng = o1_utils::tests::make_test_rng(None);
257 let c = F::rand(&mut rng);
258 let p = T::from(c);
259 let degree = unsafe { p.degree() };
260 assert_eq!(degree, 0);
261 let p = T::zero();
262 let degree = unsafe { p.degree() };
263 assert_eq!(degree, 0);
264}
265
266pub fn test_degree_random_degree<
267 F: PrimeField,
268 const N: usize,
269 const D: usize,
270 T: MVPoly<F, N, D>,
271>() {
272 let mut rng = o1_utils::tests::make_test_rng(None);
273 let max_degree: usize = rng.gen_range(1..D);
274 let p = unsafe { T::random(&mut rng, Some(max_degree)) };
275 let degree = unsafe { p.degree() };
276 assert!(degree <= max_degree);
277}
278
279pub fn test_mvpoly_add_degree_pbt<
280 F: PrimeField,
281 const N: usize,
282 const D: usize,
283 T: MVPoly<F, N, D>,
284>() {
285 let mut rng = o1_utils::tests::make_test_rng(None);
286 let degree = rng.gen_range(1..D);
287 let p1 = unsafe { T::random(&mut rng, Some(degree)) };
288 let p2 = unsafe { T::random(&mut rng, Some(degree)) };
289 let p3 = p1.clone() + p2.clone();
290 let degree_p1 = unsafe { p1.degree() };
291 let degree_p2 = unsafe { p2.degree() };
292 let degree_p3 = unsafe { p3.degree() };
293 assert!(degree_p3 <= std::cmp::max(degree_p1, degree_p2));
294}
295
296pub fn test_mvpoly_sub_degree_pbt<
297 F: PrimeField,
298 const N: usize,
299 const D: usize,
300 T: MVPoly<F, N, D>,
301>() {
302 let mut rng = o1_utils::tests::make_test_rng(None);
303 let degree = rng.gen_range(1..D);
304 let p1 = unsafe { T::random(&mut rng, Some(degree)) };
305 let p2 = unsafe { T::random(&mut rng, Some(degree)) };
306 let p3 = p1.clone() - p2.clone();
307 let degree_p1 = unsafe { p1.degree() };
308 let degree_p2 = unsafe { p2.degree() };
309 let degree_p3 = unsafe { p3.degree() };
310 assert!(degree_p3 <= std::cmp::max(degree_p1, degree_p2));
311}
312
313pub fn test_mvpoly_neg_degree_pbt<
314 F: PrimeField,
315 const N: usize,
316 const D: usize,
317 T: MVPoly<F, N, D>,
318>() {
319 let mut rng = o1_utils::tests::make_test_rng(None);
320 let degree = rng.gen_range(1..D);
321 let p1 = unsafe { T::random(&mut rng, Some(degree)) };
322 let p2 = -p1.clone();
323 let degree_p1 = unsafe { p1.degree() };
324 let degree_p2 = unsafe { p2.degree() };
325 assert_eq!(degree_p1, degree_p2);
326}
327
328pub fn test_mvpoly_mul_by_scalar_degree_pbt<
329 F: PrimeField,
330 const N: usize,
331 const D: usize,
332 T: MVPoly<F, N, D>,
333>() {
334 let mut rng = o1_utils::tests::make_test_rng(None);
335 let max_degree = rng.gen_range(1..D / 2);
336 let p1 = unsafe { T::random(&mut rng, Some(max_degree)) };
337 let c = F::rand(&mut rng);
338 let p2 = p1.clone() * T::from(c);
339 let degree_p1 = unsafe { p1.degree() };
340 let degree_p2 = unsafe { p2.degree() };
341 assert!(degree_p2 <= degree_p1);
342}
343
344pub fn test_mvpoly_mul_degree_pbt<
345 F: PrimeField,
346 const N: usize,
347 const D: usize,
348 T: MVPoly<F, N, D>,
349>() {
350 let mut rng = o1_utils::tests::make_test_rng(None);
351 let max_degree = rng.gen_range(1..D / 2);
352 let p1 = unsafe { T::random(&mut rng, Some(max_degree)) };
353 let p2 = unsafe { T::random(&mut rng, Some(max_degree)) };
354 let p3 = p1.clone() * p2.clone();
355 let degree_p1 = unsafe { p1.degree() };
356 let degree_p2 = unsafe { p2.degree() };
357 let degree_p3 = unsafe { p3.degree() };
358 assert!(degree_p3 <= degree_p1 + degree_p2);
359}
360
361pub fn test_mvpoly_mul_eval_pbt<
362 F: PrimeField,
363 const N: usize,
364 const D: usize,
365 T: MVPoly<F, N, D>,
366>() {
367 let mut rng = o1_utils::tests::make_test_rng(None);
368 let max_degree = rng.gen_range(1..D / 2);
369 let p1 = unsafe { T::random(&mut rng, Some(max_degree)) };
370 let p2 = unsafe { T::random(&mut rng, Some(max_degree)) };
371 let p3 = p1.clone() * p2.clone();
372 let random_evaluation: [F; N] = std::array::from_fn(|_| F::rand(&mut rng));
373 let eval_p1 = p1.eval(&random_evaluation);
374 let eval_p2 = p2.eval(&random_evaluation);
375 let eval_p3 = p3.eval(&random_evaluation);
376 assert_eq!(eval_p3, eval_p1 * eval_p2);
377}
378
379pub fn test_mvpoly_mul_pbt<F: PrimeField, const N: usize, const D: usize, T: MVPoly<F, N, D>>() {
380 let mut rng = o1_utils::tests::make_test_rng(None);
381 let max_degree = rng.gen_range(1..D / 2);
382 let p1 = unsafe { T::random(&mut rng, Some(max_degree)) };
383 let p2 = unsafe { T::random(&mut rng, Some(max_degree)) };
384 assert_eq!(p1.clone() * p2.clone(), p2.clone() * p1.clone());
385}
386
387pub fn test_can_be_printed_with_debug<
388 F: PrimeField,
389 const N: usize,
390 const D: usize,
391 T: MVPoly<F, N, D>,
392>() {
393 let mut rng = o1_utils::tests::make_test_rng(None);
394 let p1 = unsafe { T::random(&mut rng, None) };
395 println!("{:?}", p1);
396}
397
398pub fn test_is_zero<F: PrimeField, const N: usize, const D: usize, T: MVPoly<F, N, D>>() {
399 let mut rng = o1_utils::tests::make_test_rng(None);
400 let p1 = T::zero();
401 assert!(p1.is_zero());
402 let p2 = unsafe { T::random(&mut rng, None) };
403 assert!(!p2.is_zero());
404}
405
406pub fn test_homogeneous_eval<F: PrimeField, const N: usize, const D: usize, T: MVPoly<F, N, D>>() {
407 let mut rng = o1_utils::tests::make_test_rng(None);
408 let random_eval = std::array::from_fn(|_| F::rand(&mut rng));
409 let u = F::rand(&mut rng);
410
411 let p1 = T::one();
413 let homogenous_eval = p1.homogeneous_eval(&random_eval, u);
414 assert_eq!(homogenous_eval, u * u);
415
416 let mut p2 = T::zero();
417 let mut exp1 = [0; N];
418 exp1[0] = 1;
419 p2.add_monomial(exp1, F::one());
420 let homogenous_eval = p2.homogeneous_eval(&random_eval, u);
421 assert_eq!(homogenous_eval, random_eval[0] * u);
422
423 let mut p3 = T::zero();
424 let mut exp2 = [0; N];
425 exp2[1] = 1;
426 p3.add_monomial(exp2, F::one());
427 let homogenous_eval = p3.homogeneous_eval(&random_eval, u);
428 assert_eq!(homogenous_eval, random_eval[1] * u);
429
430 let mut p4 = T::zero();
431 let mut exp3 = [0; N];
432 exp3[0] = 1;
433 exp3[1] = 1;
434 p4.add_monomial(exp3, F::one());
435 let homogenous_eval = p4.homogeneous_eval(&random_eval, u);
436 assert_eq!(homogenous_eval, random_eval[0] * random_eval[1]);
437
438 let mut p5 = T::zero();
439 let mut exp4 = [0; N];
440 exp4[0] = 2;
441 p5.add_monomial(exp4, F::one());
442 let homogenous_eval = p5.homogeneous_eval(&random_eval, u);
443 assert_eq!(homogenous_eval, random_eval[0] * random_eval[0]);
444
445 let mut p6 = T::zero();
446 let mut exp5a = [0; N];
447 let mut exp5b = [0; N];
448 exp5a[1] = 2;
449 exp5b[0] = 2;
450 p6.add_monomial(exp5a, F::one());
451 p6.add_monomial(exp5b, F::one());
452 let homogenous_eval = p6.homogeneous_eval(&random_eval, u);
453 assert_eq!(
454 homogenous_eval,
455 random_eval[1] * random_eval[1] + random_eval[0] * random_eval[0]
456 );
457
458 let mut p7 = T::zero();
459 let mut exp6a = [0; N];
460 let mut exp6b = [0; N];
461 let mut exp6c = [0; N];
462 exp6a[1] = 2;
463 exp6b[0] = 2;
464 exp6c[0] = 1;
465 p7.add_monomial(exp6a, F::one());
466 p7.add_monomial(exp6b, F::one());
467 p7.add_monomial(exp6c, F::one());
468 p7.add_monomial([0; N], F::from(42u32));
469 let homogenous_eval = p7.homogeneous_eval(&random_eval, u);
470 assert_eq!(
471 homogenous_eval,
472 random_eval[1] * random_eval[1]
473 + random_eval[0] * random_eval[0]
474 + u * random_eval[0]
475 + u * u * F::from(42u32)
476 );
477}
478
479pub fn test_add_monomial<F: PrimeField, const N: usize, const D: usize, T: MVPoly<F, N, D>>() {
480 let mut rng = o1_utils::tests::make_test_rng(None);
481
482 let mut p1 = T::zero();
484 p1.add_monomial([0; N], F::one());
485 assert_eq!(p1, T::one());
486
487 let mut p2 = T::zero();
489 let random_c = F::rand(&mut rng);
490 p2.add_monomial([0; N], random_c);
491 assert_eq!(p2, T::from(random_c));
492
493 let mut p3 = T::zero();
494 let random_c1 = F::rand(&mut rng);
495 let random_c2 = F::rand(&mut rng);
496 let mut exp1 = [0; N];
498 let mut exp2 = [0; N];
499 exp1[0] = 1;
500 exp2[1] = 1;
501 p3.add_monomial(exp1, random_c1);
502 p3.add_monomial(exp2, random_c2);
503
504 let random_eval = std::array::from_fn(|_| F::rand(&mut rng));
505 let eval_p3 = p3.eval(&random_eval);
506 let exp_eval_p3 = random_c1 * random_eval[0] + random_c2 * random_eval[1];
507 assert_eq!(eval_p3, exp_eval_p3);
508
509 let mut p4 = T::zero();
510 let random_c1 = F::rand(&mut rng);
511 let random_c2 = F::rand(&mut rng);
512 let mut exp1 = [0; N];
514 let mut exp2 = [0; N];
515 exp1[0] = 2;
516 exp2[1] = 2;
517 p4.add_monomial(exp1, random_c1);
518 p4.add_monomial(exp2, random_c2);
519 let eval_p4 = p4.eval(&random_eval);
520 let exp_eval_p4 =
521 random_c1 * random_eval[0] * random_eval[0] + random_c2 * random_eval[1] * random_eval[1];
522 assert_eq!(eval_p4, exp_eval_p4);
523}
524
525pub fn test_is_multilinear<F: PrimeField, const N: usize, const D: usize, T: MVPoly<F, N, D>>() {
526 let mut rng = o1_utils::tests::make_test_rng(None);
527
528 let p1 = T::zero();
530 assert!(p1.is_multilinear());
531
532 let c = F::rand(&mut rng);
534 let p2 = T::from(c);
535 assert!(p2.is_multilinear());
536
537 {
539 let mut p = T::zero();
540 let c = F::rand(&mut rng);
541 let idx = rng.gen_range(0..N);
542 let monomials_exponents = std::array::from_fn(|i| if i == idx { 1 } else { 0 });
543 p.add_monomial(monomials_exponents, c);
544 assert!(p.is_multilinear());
545 }
546
547 {
549 let mut p = T::zero();
550 let c = F::rand(&mut rng);
551 let nb_var = rng.gen_range(0..D);
552 let mut monomials_exponents: [usize; N] =
553 std::array::from_fn(|i| if i <= nb_var { 1 } else { 0 });
554 monomials_exponents.shuffle(&mut rng);
555 p.add_monomial(monomials_exponents, c);
556 assert!(p.is_multilinear());
557 }
558}
559
560pub fn test_is_constant<F: PrimeField, const N: usize, const D: usize, T: MVPoly<F, N, D>>() {
561 let mut rng = o1_utils::tests::make_test_rng(None);
562 let c = F::rand(&mut rng);
563 let p = T::from(c);
564 assert!(p.is_constant());
565
566 let p = T::zero();
567 assert!(p.is_constant());
568
569 let p = {
570 let mut res = T::zero();
571 let monomial: [usize; N] = std::array::from_fn(|i| if i == 0 { 1 } else { 0 });
572 res.add_monomial(monomial, F::one());
573 res
574 };
575 assert!(!p.is_constant());
576
577 let p = {
578 let mut res = T::zero();
579 let monomial: [usize; N] = std::array::from_fn(|i| if i == 1 { 1 } else { 0 });
580 res.add_monomial(monomial, F::one());
581 res
582 };
583 assert!(!p.is_constant());
584
585 let p = unsafe { T::random(&mut rng, None) };
587 assert!(!p.is_constant());
588}