@@ -73,6 +73,7 @@ fn order_reverse(inp: &mut Vec<BigInt>) {
73
73
} ) ;
74
74
}
75
75
76
+ #[ cfg( feature = "parallel" ) ]
76
77
fn fft ( inp : Vec < BigInt > , c : & Constants , w : BigInt ) -> Vec < BigInt > {
77
78
assert ! ( inp. len( ) . is_power_of_two( ) ) ;
78
79
let mut inp = inp. clone ( ) ;
@@ -123,10 +124,62 @@ fn fft(inp: Vec<BigInt>, c: &Constants, w: BigInt) -> Vec<BigInt> {
123
124
inp
124
125
}
125
126
127
+ #[ cfg( not( feature = "parallel" ) ) ]
128
+ fn fft ( inp : Vec < BigInt > , c : & Constants , w : BigInt ) -> Vec < BigInt > {
129
+ assert ! ( inp. len( ) . is_power_of_two( ) ) ;
130
+ let mut inp = inp. clone ( ) ;
131
+ let N = inp. len ( ) ;
132
+ let MOD = BigInt :: from ( c. N ) ;
133
+ let ONE = BigInt :: from ( 1 ) ;
134
+ let mut pre: Vec < BigInt > = vec ! [ ONE ; N / 2 ] ;
135
+ let CHUNK_COUNT = 128 ;
136
+ let chunk_count = BigInt :: from ( CHUNK_COUNT ) ;
137
+
138
+ pre. chunks_mut ( CHUNK_COUNT )
139
+ . enumerate ( )
140
+ . for_each ( |( i, arr) | arr[ 0 ] = w. mod_exp ( BigInt :: from ( i) * chunk_count, MOD ) ) ;
141
+ pre. chunks_mut ( CHUNK_COUNT ) . for_each ( |x| {
142
+ ( 1 ..x. len ( ) ) . for_each ( |y| {
143
+ let _x = x. to_vec ( ) ;
144
+ x[ y] = ( w * x[ y - 1 ] ) . rem ( MOD ) ;
145
+ } )
146
+ } ) ;
147
+ order_reverse ( & mut inp) ;
148
+
149
+ let mut gap = 1 ;
150
+
151
+ while gap < inp. len ( ) {
152
+ let nchunks = inp. len ( ) / ( 2 * gap) ;
153
+ inp. chunks_mut ( 2 * gap) . for_each ( |cxi| {
154
+ let ( lo, hi) = cxi. split_at_mut ( gap) ;
155
+ lo. iter_mut ( )
156
+ . zip ( hi)
157
+ . enumerate ( )
158
+ . for_each ( |( idx, ( lo, hi) ) | {
159
+ * hi = ( * hi * pre[ nchunks * idx] ) . rem ( MOD ) ;
160
+ let neg = if * lo < * hi {
161
+ ( MOD + * lo) - * hi
162
+ } else {
163
+ * lo - * hi
164
+ } ;
165
+ * lo = if * lo + * hi >= MOD {
166
+ ( * lo + * hi) - MOD
167
+ } else {
168
+ * lo + * hi
169
+ } ;
170
+ * hi = neg;
171
+ } ) ;
172
+ } ) ;
173
+ gap *= 2 ;
174
+ }
175
+ inp
176
+ }
177
+
126
178
pub fn forward ( inp : Vec < BigInt > , c : & Constants ) -> Vec < BigInt > {
127
179
fft ( inp, c, c. w )
128
180
}
129
181
182
+ #[ cfg( feature = "parallel" ) ]
130
183
pub fn inverse ( inp : Vec < BigInt > , c : & Constants ) -> Vec < BigInt > {
131
184
let mut inv = BigInt :: from ( inp. len ( ) ) ;
132
185
let _ = inv. set_mod ( c. N ) ;
@@ -137,6 +190,17 @@ pub fn inverse(inp: Vec<BigInt>, c: &Constants) -> Vec<BigInt> {
137
190
res
138
191
}
139
192
193
+ #[ cfg( not( feature = "parallel" ) ) ]
194
+ pub fn inverse ( inp : Vec < BigInt > , c : & Constants ) -> Vec < BigInt > {
195
+ let mut inv = BigInt :: from ( inp. len ( ) ) ;
196
+ let _ = inv. set_mod ( c. N ) ;
197
+ let inv = inv. invert ( ) ;
198
+ let w = c. w . invert ( ) ;
199
+ let mut res = fft ( inp, c, w) ;
200
+ res. iter_mut ( ) . for_each ( |x| * x = ( inv * ( * x) ) . rem ( c. N ) ) ;
201
+ res
202
+ }
203
+
140
204
#[ cfg( test) ]
141
205
mod tests {
142
206
use rand:: Rng ;
0 commit comments