ark_poly/polynomial/multivariate/
mod.rs1use ark_ff::Field;
3use ark_serialize::{CanonicalDeserialize, CanonicalSerialize};
4use ark_std::{
5 cmp::Ordering,
6 fmt::{Debug, Error, Formatter},
7 hash::Hash,
8 ops::Deref,
9 vec::*,
10};
11
12#[cfg(feature = "parallel")]
13use rayon::prelude::*;
14
15mod sparse;
16pub use sparse::SparsePolynomial;
17
18pub trait Term:
20 Clone
21 + PartialOrd
22 + Ord
23 + PartialEq
24 + Eq
25 + Hash
26 + Default
27 + Debug
28 + Deref<Target = [(usize, usize)]>
29 + Send
30 + Sync
31 + CanonicalSerialize
32 + CanonicalDeserialize
33{
34 fn new(term: Vec<(usize, usize)>) -> Self;
36
37 fn degree(&self) -> usize;
40
41 fn vars(&self) -> Vec<usize>;
43
44 fn powers(&self) -> Vec<usize>;
46
47 fn is_constant(&self) -> bool;
49
50 fn evaluate<F: Field>(&self, p: &[F]) -> F;
52}
53
54#[derive(Clone, PartialEq, Eq, Hash, Default, CanonicalSerialize, CanonicalDeserialize)]
57pub struct SparseTerm(Vec<(usize, usize)>);
58
59impl SparseTerm {
60 fn combine(term: &[(usize, usize)]) -> Vec<(usize, usize)> {
62 let mut term_dedup: Vec<(usize, usize)> = Vec::new();
63 for (var, pow) in term {
64 if let Some(prev) = term_dedup.last_mut() {
65 if prev.0 == *var {
66 prev.1 += pow;
67 continue;
68 }
69 }
70 term_dedup.push((*var, *pow));
71 }
72 term_dedup
73 }
74}
75
76impl Term for SparseTerm {
77 fn new(mut term: Vec<(usize, usize)>) -> Self {
79 term.retain(|(_, pow)| *pow != 0);
81 if term.len() > 1 {
84 term.sort_by(|(v1, _), (v2, _)| v1.cmp(v2));
85 term = Self::combine(&term);
86 }
87 Self(term)
88 }
89
90 fn degree(&self) -> usize {
92 self.iter().fold(0, |sum, acc| sum + acc.1)
93 }
94
95 fn vars(&self) -> Vec<usize> {
97 self.iter().map(|(v, _)| *v).collect()
98 }
99
100 fn powers(&self) -> Vec<usize> {
102 self.iter().map(|(_, p)| *p).collect()
103 }
104
105 fn is_constant(&self) -> bool {
107 self.len() == 0 || self.degree() == 0
108 }
109
110 fn evaluate<F: Field>(&self, point: &[F]) -> F {
112 cfg_into_iter!(self)
113 .map(|(var, power)| point[*var].pow([*power as u64]))
114 .product()
115 }
116}
117
118impl Debug for SparseTerm {
119 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
120 for variable in self.iter() {
121 if variable.1 == 1 {
122 write!(f, " * x_{}", variable.0)?;
123 } else {
124 write!(f, " * x_{}^{}", variable.0, variable.1)?;
125 }
126 }
127 Ok(())
128 }
129}
130
131impl Deref for SparseTerm {
132 type Target = [(usize, usize)];
133
134 fn deref(&self) -> &[(usize, usize)] {
135 &self.0
136 }
137}
138
139impl PartialOrd for SparseTerm {
140 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
144 if self.degree() != other.degree() {
145 Some(self.degree().cmp(&other.degree()))
146 } else {
147 for (cur, other) in self.iter().zip(other.iter()) {
150 if other.0 == cur.0 {
151 if cur.1 != other.1 {
152 return Some((cur.1).cmp(&other.1));
153 }
154 } else {
155 return Some((other.0).cmp(&cur.0));
156 }
157 }
158 Some(Ordering::Equal)
159 }
160 }
161}
162
163impl Ord for SparseTerm {
164 fn cmp(&self, other: &Self) -> Ordering {
165 self.partial_cmp(other).unwrap()
166 }
167}