@@ -10,19 +10,7 @@ use std::{
10
10
} ;
11
11
12
12
/// Trait for arithmetic for univariate polynomials in Fp[X]
13
- pub trait Poly :
14
- Index < usize >
15
- + IndexMut < usize >
16
- + Sized
17
- + Neg < Output = Self >
18
- + Add < Output = Self >
19
- + AddAssign
20
- + Sub < Output = Self >
21
- + SubAssign
22
- + Mul < Output = Self >
23
- + MulAssign
24
- + Display
25
- {
13
+ pub trait Poly : Index < usize > + IndexMut < usize > + Sized + Display {
26
14
// TODO
27
15
}
28
16
@@ -47,14 +35,28 @@ impl<Fp: FpTrait> Polynomial<Fp> {
47
35
self . coeffs . len ( )
48
36
}
49
37
50
- /// The degree of the polynomial. TODO: should we trim trailing zeros? If so, how often?
51
- /// We return None for the zero polynomial (instead of -inf which is a bit too big for my
52
- /// computer...)
53
- fn degree ( & self ) -> Option < usize > {
54
- if self . coeffs . is_empty ( ) {
38
+ /// Truncate leading zeros from the polynomial
39
+ fn truncate_leading_zeros ( & mut self ) {
40
+ // find the index of the first non-zero element
41
+ let mut i = self . len ( ) - 1 ;
42
+ while i > 0 && self . coeffs [ i] . is_zero ( ) == u32:: MAX {
43
+ i -= 1 ;
44
+ }
45
+ self . coeffs . truncate ( i) ;
46
+ }
47
+
48
+ /// Return the degree of the polynomial.
49
+ // TODO: should we trim trailing zeros and mutate while computing the degree or do the following
50
+ // and allow trailing zeros to remain.
51
+ pub fn degree ( & self ) -> Option < usize > {
52
+ let mut i = self . len ( ) - 1 ;
53
+ while i > 0 && self . coeffs [ i] . is_zero ( ) == u32:: MAX {
54
+ i -= 1 ;
55
+ }
56
+ if i == 0 && self . coeffs [ 0 ] . is_zero ( ) == u32:: MAX {
55
57
None
56
58
} else {
57
- Some ( self . len ( ) - 1 )
59
+ Some ( i )
58
60
}
59
61
}
60
62
@@ -103,30 +105,17 @@ impl<Fp: FpTrait> Polynomial<Fp> {
103
105
is_zero
104
106
}
105
107
106
- /// Set self to it's negative.
107
- fn set_neg ( & mut self ) {
108
- for x in self . coeffs . iter_mut ( ) {
109
- x. set_neg ( ) ;
110
- }
111
- }
112
-
113
- /// Set self <- self + other
114
- // TODO: should we assume other has length smaller or equal to
115
- // self, or dynamically extend?
116
- fn set_add ( & mut self , other : & Self ) {
117
- let k = self . len ( ) . min ( other. len ( ) ) ;
118
- for i in 0 ..k {
119
- self . coeffs [ i] += other[ i] ;
108
+ /// Compute f <-- f + g, assumes that the length of f and g are the same.
109
+ fn add_into ( f : & mut [ Fp ] , g : & [ Fp ] ) {
110
+ for i in 0 ..g. len ( ) {
111
+ f[ i] += g[ i] ;
120
112
}
121
113
}
122
114
123
- /// Set self <- self - other
124
- // TODO: should we assume other has length smaller or equal to
125
- // self, or dynamically extend?
126
- fn set_sub ( & mut self , other : & Self ) {
127
- let k = self . len ( ) . min ( other. len ( ) ) ;
128
- for i in 0 ..k {
129
- self . coeffs [ i] -= other[ i] ;
115
+ /// Compute f <-- f - g, assumes that the length of f and g are the same.
116
+ fn sub_into ( f : & mut [ Fp ] , g : & [ Fp ] ) {
117
+ for i in 0 ..g. len ( ) {
118
+ f[ i] -= g[ i] ;
130
119
}
131
120
}
132
121
@@ -143,6 +132,29 @@ impl<Fp: FpTrait> Polynomial<Fp> {
143
132
}
144
133
}
145
134
135
+ /// Set self to it's negative.
136
+ fn set_neg ( & mut self ) {
137
+ for x in self . coeffs . iter_mut ( ) {
138
+ x. set_neg ( ) ;
139
+ }
140
+ }
141
+
142
+ /// Set self <- self + other
143
+ fn set_add ( & mut self , other : & Self ) {
144
+ if self . len ( ) < other. len ( ) {
145
+ self . coeffs . resize ( other. len ( ) , Fp :: ZERO ) ;
146
+ }
147
+ Self :: add_into ( & mut self . coeffs , & other. coeffs ) ;
148
+ }
149
+
150
+ /// Set self <- self - other
151
+ fn set_sub ( & mut self , other : & Self ) {
152
+ if self . len ( ) < other. len ( ) {
153
+ self . coeffs . resize ( other. len ( ) , Fp :: ZERO ) ;
154
+ }
155
+ Self :: sub_into ( & mut self . coeffs , & other. coeffs ) ;
156
+ }
157
+
146
158
/// Set self <- self * other
147
159
fn set_mul ( & mut self , other : & Self ) {
148
160
let mut fg_coeffs = vec ! [ Fp :: ZERO ; self . len( ) + other. len( ) - 1 ] ;
@@ -179,6 +191,7 @@ impl<Fp: FpTrait> Polynomial<Fp> {
179
191
}
180
192
181
193
/// Evaluate a polynomial at a value `a`
194
+ // TODO: is this over engineered?
182
195
pub fn evaluate ( & self , a : & Fp ) -> Fp {
183
196
// Handle degree 0 and 1 cases early.
184
197
if self . len ( ) == 0 {
@@ -251,29 +264,18 @@ impl<Fp: FpTrait> IndexMut<usize> for Polynomial<Fp> {
251
264
}
252
265
}
253
266
254
- impl < Fp : FpTrait > Neg for Polynomial < Fp > {
267
+ impl < Fp : FpTrait > Neg for & Polynomial < Fp > {
255
268
type Output = Polynomial < Fp > ;
256
269
257
270
#[ inline( always) ]
258
271
fn neg ( self ) -> Polynomial < Fp > {
259
- let mut r = self ;
272
+ let mut r = self . clone ( ) ;
260
273
r. set_neg ( ) ;
261
274
r
262
275
}
263
276
}
264
277
265
- impl < Fp : FpTrait > Add for Polynomial < Fp > {
266
- type Output = Polynomial < Fp > ;
267
-
268
- #[ inline( always) ]
269
- fn add ( self , other : Polynomial < Fp > ) -> Polynomial < Fp > {
270
- let mut r = self ;
271
- r. set_add ( & other) ;
272
- r
273
- }
274
- }
275
-
276
- impl < Fp : FpTrait > Add for & Polynomial < Fp > {
278
+ impl < Fp : FpTrait > Add < & Polynomial < Fp > > for & Polynomial < Fp > {
277
279
type Output = Polynomial < Fp > ;
278
280
279
281
#[ inline( always) ]
@@ -284,32 +286,14 @@ impl<Fp: FpTrait> Add for &Polynomial<Fp> {
284
286
}
285
287
}
286
288
287
- impl < Fp : FpTrait > AddAssign for Polynomial < Fp > {
288
- #[ inline( always) ]
289
- fn add_assign ( & mut self , other : Polynomial < Fp > ) {
290
- self . set_add ( & other) ;
291
- }
292
- }
293
-
294
289
impl < Fp : FpTrait > AddAssign < & Polynomial < Fp > > for Polynomial < Fp > {
295
290
#[ inline( always) ]
296
291
fn add_assign ( & mut self , other : & Polynomial < Fp > ) {
297
292
self . set_add ( other) ;
298
293
}
299
294
}
300
295
301
- impl < Fp : FpTrait > Sub for Polynomial < Fp > {
302
- type Output = Polynomial < Fp > ;
303
-
304
- #[ inline( always) ]
305
- fn sub ( self , other : Polynomial < Fp > ) -> Polynomial < Fp > {
306
- let mut r = self ;
307
- r. set_sub ( & other) ;
308
- r
309
- }
310
- }
311
-
312
- impl < Fp : FpTrait > Sub for & Polynomial < Fp > {
296
+ impl < Fp : FpTrait > Sub < & Polynomial < Fp > > for & Polynomial < Fp > {
313
297
type Output = Polynomial < Fp > ;
314
298
315
299
#[ inline( always) ]
@@ -320,32 +304,14 @@ impl<Fp: FpTrait> Sub for &Polynomial<Fp> {
320
304
}
321
305
}
322
306
323
- impl < Fp : FpTrait > SubAssign for Polynomial < Fp > {
324
- #[ inline( always) ]
325
- fn sub_assign ( & mut self , other : Polynomial < Fp > ) {
326
- self . set_sub ( & other) ;
327
- }
328
- }
329
-
330
307
impl < Fp : FpTrait > SubAssign < & Polynomial < Fp > > for Polynomial < Fp > {
331
308
#[ inline( always) ]
332
309
fn sub_assign ( & mut self , other : & Polynomial < Fp > ) {
333
310
self . set_sub ( other) ;
334
311
}
335
312
}
336
313
337
- impl < Fp : FpTrait > Mul for Polynomial < Fp > {
338
- type Output = Polynomial < Fp > ;
339
-
340
- #[ inline( always) ]
341
- fn mul ( self , other : Polynomial < Fp > ) -> Polynomial < Fp > {
342
- let mut r = self ;
343
- r. set_mul ( & other) ;
344
- r
345
- }
346
- }
347
-
348
- impl < Fp : FpTrait > Mul for & Polynomial < Fp > {
314
+ impl < Fp : FpTrait > Mul < & Polynomial < Fp > > for & Polynomial < Fp > {
349
315
type Output = Polynomial < Fp > ;
350
316
351
317
#[ inline( always) ]
@@ -356,13 +322,6 @@ impl<Fp: FpTrait> Mul for &Polynomial<Fp> {
356
322
}
357
323
}
358
324
359
- impl < Fp : FpTrait > MulAssign for Polynomial < Fp > {
360
- #[ inline( always) ]
361
- fn mul_assign ( & mut self , other : Polynomial < Fp > ) {
362
- self . set_mul ( & other) ;
363
- }
364
- }
365
-
366
325
impl < Fp : FpTrait > MulAssign < & Polynomial < Fp > > for Polynomial < Fp > {
367
326
#[ inline( always) ]
368
327
fn mul_assign ( & mut self , other : & Polynomial < Fp > ) {
0 commit comments