1
- use std:: fmt:: Debug ;
1
+ use std:: { borrow :: Borrow , fmt:: Debug } ;
2
2
3
3
use generic_array:: { ArrayLength , GenericArray } ;
4
4
use typenum:: { Unsigned , U1 } ;
5
5
6
6
use crate :: ff:: { Field , PrimeField , Serializable } ;
7
7
8
- /// A degree `N-1` polynomial is stored as `N` points `(x,y)`
9
- /// where the "x coordinates" of the input points are `x_0` to `x_N` are `F::ZERO` to `(N-1)*F::ONE`
10
- /// Therefore, we only need to store the `y` coordinates.
11
- #[ derive( Debug , PartialEq , Clone ) ]
12
- pub struct Polynomial < F : Field , N : ArrayLength > {
13
- y_coordinates : GenericArray < F , N > ,
14
- }
15
-
16
8
/// The Canonical Lagrange denominator is defined as the denominator of the Lagrange base polynomials
17
9
/// `https://en.wikipedia.org/wiki/Lagrange_polynomial`
18
10
/// where the "x coordinates" of the input points are `x_0` to `x_N` are `F::ZERO` to `(N-1)*F::ONE`
@@ -99,16 +91,25 @@ where
99
91
N : ArrayLength ,
100
92
M : ArrayLength ,
101
93
{
102
- /// This function uses the `LagrangeTable` to evaluate `polynomial` on the specified output "x coordinates"
103
- /// outputs the "y coordinates" such that `(x,y)` lies on `polynomial`
104
- pub fn eval ( & self , polynomial : & Polynomial < F , N > ) -> GenericArray < F , M > {
94
+ /// This function uses the `LagrangeTable` to evaluate `polynomial` on the _output_ "x coordinates"
95
+ /// that were used to generate this table.
96
+ /// It is assumed that the `y_coordinates` provided to this function correspond the values of the _input_ "x coordinates"
97
+ /// that were used to generate this table.
98
+ pub fn eval < I , J > ( & self , y_coordinates : I ) -> GenericArray < F , M >
99
+ where
100
+ I : IntoIterator < Item = J > + Copy ,
101
+ I :: IntoIter : ExactSizeIterator ,
102
+ J : Borrow < F > ,
103
+ {
104
+ debug_assert_eq ! ( y_coordinates. into_iter( ) . len( ) , N :: USIZE ) ;
105
+
105
106
self . table
106
107
. iter ( )
107
108
. map ( |table_row| {
108
109
table_row
109
110
. iter ( )
110
- . zip ( polynomial . y_coordinates . iter ( ) )
111
- . fold ( F :: ZERO , |acc, ( & base, & y) | acc + base * y )
111
+ . zip ( y_coordinates)
112
+ . fold ( F :: ZERO , |acc, ( & base, y) | acc + base * ( * y . borrow ( ) ) )
112
113
} )
113
114
. collect ( )
114
115
}
@@ -168,84 +169,77 @@ where
168
169
169
170
#[ cfg( all( test, unit_test) ) ]
170
171
mod test {
171
- use std:: fmt:: Debug ;
172
+ use std:: { borrow :: Borrow , fmt:: Debug } ;
172
173
173
- use generic_array:: { sequence :: GenericSequence , ArrayLength , GenericArray } ;
174
+ use generic_array:: { ArrayLength , GenericArray } ;
174
175
use proptest:: { prelude:: * , proptest} ;
175
176
use typenum:: { U1 , U32 , U7 , U8 } ;
176
177
177
178
use crate :: {
178
- ff:: Field ,
179
+ ff:: PrimeField ,
179
180
protocol:: ipa_prf:: malicious_security:: lagrange:: {
180
- CanonicalLagrangeDenominator , LagrangeTable , Polynomial ,
181
+ CanonicalLagrangeDenominator , LagrangeTable ,
181
182
} ,
182
183
} ;
183
184
184
185
type TestField = crate :: ff:: Fp32BitPrime ;
185
186
186
187
#[ derive( Debug , PartialEq , Clone ) ]
187
- struct MonomialFormPolynomial < F : Field , N : ArrayLength > {
188
+ struct MonomialFormPolynomial < F : PrimeField , N : ArrayLength > {
188
189
coefficients : GenericArray < F , N > ,
189
190
}
190
191
191
192
impl < F , N > MonomialFormPolynomial < F , N >
192
193
where
193
- F : Field ,
194
+ F : PrimeField ,
194
195
N : ArrayLength ,
195
196
{
197
+ fn gen_y_values_of_canonical_points ( self ) -> GenericArray < F , N > {
198
+ // Sadly, we cannot just use the range (0..N::U128) because it does not implement ExactSizeIterator
199
+ let canonical_points =
200
+ ( 0 ..N :: USIZE ) . map ( |i| F :: try_from ( u128:: try_from ( i) . unwrap ( ) ) . unwrap ( ) ) ;
201
+ self . eval ( canonical_points)
202
+ }
203
+
196
204
/// test helper function that evaluates a polynomial in monomial form, i.e. `sum_i c_i x^i` on points `x_output`
197
205
/// where `c_0` to `c_N` are stored in `polynomial`
198
- fn eval < M > ( & self , x_output : & GenericArray < F , M > ) -> GenericArray < F , M >
206
+ fn eval < M , I , J > ( & self , x_output : I ) -> GenericArray < F , M >
199
207
where
208
+ I : IntoIterator < Item = J > ,
209
+ I :: IntoIter : ExactSizeIterator ,
210
+ J : Borrow < F > ,
200
211
M : ArrayLength ,
201
212
{
202
213
x_output
203
- . iter ( )
204
- . map ( |& x| {
214
+ . into_iter ( )
215
+ . map ( |x| {
205
216
// monomial base, i.e. `x^k`
206
217
// evaluate p via `sum_k coefficient_k * x^k`
207
218
let ( _, y) = self
208
219
. coefficients
209
220
. iter ( )
210
221
. fold ( ( F :: ONE , F :: ZERO ) , |( base, y) , & coef| {
211
- ( base * x , y + coef * base)
222
+ ( base * ( * x . borrow ( ) ) , y + coef * base)
212
223
} ) ;
213
224
y
214
225
} )
215
226
. collect ( )
216
227
}
217
228
}
218
229
219
- impl < F , N > From < MonomialFormPolynomial < F , N > > for Polynomial < F , N >
220
- where
221
- F : Field + TryFrom < u128 > ,
222
- <F as TryFrom < u128 > >:: Error : Debug ,
223
- N : ArrayLength ,
224
- {
225
- fn from ( value : MonomialFormPolynomial < F , N > ) -> Self {
226
- let canonical_points: GenericArray < F , N > =
227
- GenericArray :: generate ( |i| F :: try_from ( u128:: try_from ( i) . unwrap ( ) ) . unwrap ( ) ) ;
228
- Polynomial {
229
- y_coordinates : value. eval ( & canonical_points) ,
230
- }
231
- }
232
- }
233
-
234
230
fn lagrange_single_output_point_using_new (
235
231
output_point : TestField ,
236
232
input_points : [ TestField ; 32 ] ,
237
233
) {
238
234
let polynomial_monomial_form = MonomialFormPolynomial {
239
235
coefficients : GenericArray :: < TestField , U32 > :: from_array ( input_points) ,
240
236
} ;
241
- let output_expected = polynomial_monomial_form. eval (
242
- & GenericArray :: < TestField , U1 > :: from_array ( [ output_point; 1 ] ) ,
243
- ) ;
244
- let polynomial = Polynomial :: from ( polynomial_monomial_form. clone ( ) ) ;
237
+ let output_expected = polynomial_monomial_form. eval ( & [ output_point] ) ;
245
238
let denominator = CanonicalLagrangeDenominator :: < TestField , U32 > :: new ( ) ;
246
239
// generate table using new
247
240
let lagrange_table = LagrangeTable :: < TestField , U32 , U1 > :: new ( & denominator, & output_point) ;
248
- let output = lagrange_table. eval ( & polynomial) ;
241
+ let output =
242
+ lagrange_table. eval ( & polynomial_monomial_form. gen_y_values_of_canonical_points ( ) ) ;
249
243
assert_eq ! ( output, output_expected) ;
250
244
}
251
245
@@ -261,15 +255,14 @@ mod test {
261
255
coefficients : GenericArray :: < TestField , U8 > :: from_array ( input_points) ,
262
256
} ;
263
257
// the canonical x coordinates are 0..7, the outputs use coordinates 8..15:
264
- let x_coordinates_output = GenericArray :: < _ , U7 > :: generate ( |i| {
265
- TestField :: try_from ( u128:: try_from ( i) . unwrap ( ) + 8 ) . unwrap ( )
266
- } ) ;
267
- let output_expected = polynomial_monomial_form. eval ( & x_coordinates_output) ;
268
- let polynomial = Polynomial :: from ( polynomial_monomial_form. clone ( ) ) ;
258
+ let x_coordinates_output =
259
+ ( 0 ..7 ) . map ( |i| TestField :: try_from ( u128:: try_from ( i) . unwrap ( ) + 8 ) . unwrap ( ) ) ;
260
+ let output_expected = polynomial_monomial_form. eval ( x_coordinates_output) ;
269
261
let denominator = CanonicalLagrangeDenominator :: < TestField , U8 > :: new ( ) ;
270
262
// generate table using from
271
263
let lagrange_table = LagrangeTable :: < TestField , U8 , U7 > :: from ( denominator) ;
272
- let output = lagrange_table. eval ( & polynomial) ;
264
+ let output =
265
+ lagrange_table. eval ( & polynomial_monomial_form. gen_y_values_of_canonical_points ( ) ) ;
273
266
assert_eq ! ( output, output_expected) ;
274
267
}
275
268
0 commit comments