3
3
use fp2:: traits:: Fp as FpTrait ;
4
4
5
5
use core:: ops:: { Add , AddAssign , Mul , MulAssign , Neg , Sub , SubAssign } ;
6
- use std:: { fmt:: Display , ops:: Index } ;
6
+ use std:: {
7
+ fmt:: Display ,
8
+ ops:: { Index , IndexMut } ,
9
+ } ;
7
10
8
11
/// Trait for arithmetic for univariate polynomials in Fp[X]
9
12
pub trait Poly :
10
13
Index < usize >
14
+ + IndexMut < usize >
11
15
+ Sized
12
16
+ Neg < Output = Self >
13
17
+ Add < Output = Self >
@@ -43,7 +47,19 @@ impl<Fp: FpTrait> Polynomial<Fp> {
43
47
}
44
48
}
45
49
46
- /// Set self to it's negative
50
+ /// Reverse the coefficients of self in place.
51
+ fn reverse_into ( & mut self ) {
52
+ self . coeffs . reverse ( ) ;
53
+ }
54
+
55
+ /// Return the polynomial with coefficents reversed.
56
+ pub fn reverse ( self ) -> Polynomial < Fp > {
57
+ let mut r = self ;
58
+ r. reverse_into ( ) ;
59
+ r
60
+ }
61
+
62
+ /// Set self to it's negative.
47
63
fn set_neg ( & mut self ) {
48
64
for x in self . coeffs . iter_mut ( ) {
49
65
x. set_neg ( ) ;
@@ -70,8 +86,52 @@ impl<Fp: FpTrait> Polynomial<Fp> {
70
86
}
71
87
}
72
88
73
- fn set_mul ( & mut self , _other : & Self ) {
74
- todo ! ( )
89
+ /// Compute f * g with O(len(f) * len(g)) Fq multiplications using
90
+ /// schoolbook multiplication. Assumes that fg has enough space for
91
+ /// the result (len(f) + len(g) - 2).
92
+ fn schoolbook_multiplication ( fg : & mut [ Fp ] , f : & [ Fp ] , g : & [ Fp ] ) {
93
+ for i in 0 ..f. len ( ) {
94
+ for j in 0 ..g. len ( ) {
95
+ // TODO: this could be sped up when we know c[i + j] is zero
96
+ // which happens when i = 0 or when j + 1 = len(other)
97
+ fg[ i + j] += f[ i] * g[ j]
98
+ }
99
+ }
100
+ }
101
+
102
+ /// Set self <- self * other
103
+ fn set_mul ( & mut self , other : & Self ) {
104
+ let mut fg_coeffs = vec ! [ Fp :: ZERO ; self . len( ) + other. len( ) - 2 ] ;
105
+ Self :: schoolbook_multiplication ( & mut fg_coeffs, & self . coeffs , & other. coeffs ) ;
106
+ self . coeffs = fg_coeffs;
107
+ }
108
+
109
+ /// Multiply all coefficients of the polynomial by a element of the finite field.
110
+ pub fn scale_into ( & mut self , c : & Fp ) {
111
+ for x in self . coeffs . iter_mut ( ) {
112
+ * x *= * c;
113
+ }
114
+ }
115
+
116
+ /// Return c * self for some c in the finite field.
117
+ pub fn scale ( self , c : & Fp ) -> Polynomial < Fp > {
118
+ let mut r = self ;
119
+ r. scale_into ( c) ;
120
+ r
121
+ }
122
+
123
+ /// Multiply all coefficients of the polynomial by a small value.
124
+ pub fn scale_small_into ( & mut self , k : i32 ) {
125
+ for x in self . coeffs . iter_mut ( ) {
126
+ x. set_mul_small ( k) ;
127
+ }
128
+ }
129
+
130
+ /// Return c * self for some small c
131
+ pub fn scale_small ( self , k : i32 ) -> Polynomial < Fp > {
132
+ let mut r = self ;
133
+ r. scale_small_into ( k) ;
134
+ r
75
135
}
76
136
}
77
137
@@ -85,6 +145,12 @@ impl<Fp: FpTrait> Index<usize> for Polynomial<Fp> {
85
145
}
86
146
}
87
147
148
+ impl < Fp : FpTrait > IndexMut < usize > for Polynomial < Fp > {
149
+ fn index_mut ( & mut self , index : usize ) -> & mut Self :: Output {
150
+ self . coeffs . get_mut ( index) . expect ( "Index out of bounds" )
151
+ }
152
+ }
153
+
88
154
impl < Fp : FpTrait > Neg for Polynomial < Fp > {
89
155
type Output = Polynomial < Fp > ;
90
156
0 commit comments