1 | #include "fast_mult.h" |
---|
2 | #include "kbuckets.h" |
---|
3 | typedef poly fastmultrec(poly f, poly g, ring r); |
---|
4 | static const int pass_option=1; |
---|
5 | static int mults=0; |
---|
6 | int Mults(){ |
---|
7 | return mults; |
---|
8 | } |
---|
9 | static void degsplit(poly p,int n,poly &p1,poly&p2, int vn, ring r){ |
---|
10 | poly erg1_i, erg2_i; |
---|
11 | erg1_i=NULL; |
---|
12 | erg2_i=NULL; |
---|
13 | while(p){ |
---|
14 | if(p_GetExp(p,vn,r)>=n){ |
---|
15 | if (p1==NULL){ |
---|
16 | p1=p; |
---|
17 | } else{ |
---|
18 | pNext(erg1_i)=p; |
---|
19 | } |
---|
20 | erg1_i=p; |
---|
21 | } else{ |
---|
22 | if (p2==NULL){ |
---|
23 | p2=p; |
---|
24 | } else{ |
---|
25 | pNext(erg2_i)=p; |
---|
26 | } |
---|
27 | erg2_i=p; |
---|
28 | } |
---|
29 | p=pNext(p); |
---|
30 | } |
---|
31 | if(erg2_i){ |
---|
32 | pNext(erg2_i)=NULL; |
---|
33 | } |
---|
34 | if (erg1_i){ |
---|
35 | pNext(erg1_i)=NULL; |
---|
36 | } |
---|
37 | |
---|
38 | } |
---|
39 | static void div_by_x_power_n(poly p, int n, int vn, ring r){ |
---|
40 | while(p){ |
---|
41 | assume(p_GetExp(p,vn,r)>=n); |
---|
42 | int e=p_GetExp(p,vn,r); |
---|
43 | p_SetExp(p,vn,e-n,r); |
---|
44 | p=pNext(p); |
---|
45 | } |
---|
46 | } |
---|
47 | |
---|
48 | static poly do_unifastmult(poly f,int df,poly g,int dg, int vn, fastmultrec rec, ring r){ |
---|
49 | int n=1; |
---|
50 | if ((f==NULL)||(g==NULL)) return NULL; |
---|
51 | //int df=pGetExp(f,vn);//pFDeg(f); |
---|
52 | // int dg=pGetExp(g,vn);//pFDeg(g); |
---|
53 | |
---|
54 | int dm; |
---|
55 | if(df>dg){ |
---|
56 | dm=df; |
---|
57 | }else{ |
---|
58 | dm=dg; |
---|
59 | } |
---|
60 | while(n<=dm) |
---|
61 | { |
---|
62 | n*=2; |
---|
63 | } |
---|
64 | if(n==1){ |
---|
65 | return(pp_Mult_qq(f,g,r)); |
---|
66 | } |
---|
67 | |
---|
68 | int pot=n/2; |
---|
69 | assume(pot*2==n); |
---|
70 | |
---|
71 | |
---|
72 | //splitting |
---|
73 | poly f1=NULL; |
---|
74 | poly f0=NULL;//f-(x^(pot)*F1); |
---|
75 | degsplit(p_Copy(f,r),pot,f1,f0,vn,r); |
---|
76 | div_by_x_power_n(f1,pot,vn,r); |
---|
77 | |
---|
78 | poly g1=NULL; |
---|
79 | poly g0=NULL; |
---|
80 | degsplit(p_Copy(g,r),pot,g1,g0,vn,r); |
---|
81 | div_by_x_power_n(g1,pot,vn,r); |
---|
82 | |
---|
83 | //p00, p11 |
---|
84 | poly p00=rec(f0,g0,r);//unifastmult(f0,g0); |
---|
85 | poly p11=rec(f1,g1,r); |
---|
86 | |
---|
87 | //construct erg, factor |
---|
88 | poly erg=NULL; |
---|
89 | poly factor=p_ISet(1,r); |
---|
90 | |
---|
91 | p_SetExp(factor,vn,n,r); |
---|
92 | erg=pp_Mult_mm(p11,factor,r); |
---|
93 | erg=p_Add_q(erg,p_Copy(p00,r),r); |
---|
94 | |
---|
95 | |
---|
96 | |
---|
97 | |
---|
98 | |
---|
99 | if((f1!=NULL) &&(f0!=NULL) &&(g0!=NULL) && (g1!=NULL)){ |
---|
100 | //if(true){ |
---|
101 | //eat up f0,f1,g0,g1 |
---|
102 | poly s1=p_Add_q(f0,f1,r); |
---|
103 | poly s2=p_Add_q(g0,g1,r); |
---|
104 | poly pbig=rec(s1,s2,r); |
---|
105 | p_Delete(&s1,r); |
---|
106 | p_Delete(&s2,r); |
---|
107 | |
---|
108 | |
---|
109 | //eat up pbig |
---|
110 | poly sum=pbig; |
---|
111 | p_SetExp(factor,vn,pot,r); |
---|
112 | |
---|
113 | //eat up p00 |
---|
114 | sum=p_Add_q(sum,p_Neg(p00,r),r); |
---|
115 | |
---|
116 | //eat up p11 |
---|
117 | sum=p_Add_q(sum,p_Neg(p11,r),r); |
---|
118 | |
---|
119 | |
---|
120 | sum=p_Mult_mm(sum,factor,r); |
---|
121 | |
---|
122 | |
---|
123 | //eat up sum |
---|
124 | erg=p_Add_q(sum,erg,r); |
---|
125 | } else { |
---|
126 | //eat up f0,f1,g0,g1 |
---|
127 | poly s1=rec(f0,g1,r); |
---|
128 | poly s2=rec(g0,f1,r); |
---|
129 | p_SetExp(factor,vn,pot,r); |
---|
130 | poly h=p_Mult_mm(((s1!=NULL)?s1:s2),factor,r); |
---|
131 | p_Delete(&f1,r); |
---|
132 | p_Delete(&f0,r); |
---|
133 | p_Delete(&g0,r); |
---|
134 | p_Delete(&g1,r); |
---|
135 | p_Delete(&p00,r); |
---|
136 | p_Delete(&p11,r); |
---|
137 | erg=p_Add_q(erg,h,r); |
---|
138 | } |
---|
139 | |
---|
140 | |
---|
141 | p_Delete(&factor,r); |
---|
142 | |
---|
143 | |
---|
144 | |
---|
145 | return(erg); |
---|
146 | } |
---|
147 | |
---|
148 | // poly do_unifastmult_buckets(poly f,poly g){ |
---|
149 | |
---|
150 | |
---|
151 | |
---|
152 | |
---|
153 | // int n=1; |
---|
154 | // if ((f==NULL)||(g==NULL)) return NULL; |
---|
155 | // int df=pGetExp(f,1);//pFDeg(f); |
---|
156 | // int dg=pGetExp(g,1);//pFDeg(g); |
---|
157 | |
---|
158 | // int dm; |
---|
159 | // if(df>dg){ |
---|
160 | // dm=df; |
---|
161 | // }else{ |
---|
162 | // dm=dg; |
---|
163 | // } |
---|
164 | // while(n<=dm) |
---|
165 | // { |
---|
166 | // n*=2; |
---|
167 | // } |
---|
168 | // int pseudo_len=0; |
---|
169 | // if(n==1){ |
---|
170 | // return ppMult_qq(f,g); |
---|
171 | |
---|
172 | // } |
---|
173 | // kBucket_pt erg_bucket= kBucketCreate(currRing); |
---|
174 | // kBucketInit(erg_bucket,NULL,0 /*pLength(P.p)*/); |
---|
175 | |
---|
176 | // int pot=n/2; |
---|
177 | // assume(pot*2==n); |
---|
178 | |
---|
179 | |
---|
180 | // //splitting |
---|
181 | // poly f1=NULL; |
---|
182 | // poly f0=NULL;//f-(x^(pot)*F1); |
---|
183 | // degsplit(pCopy(f),pot,f1,f0); |
---|
184 | // div_by_x_power_n(f1,pot); |
---|
185 | // poly g1=NULL; |
---|
186 | // poly g0=NULL; |
---|
187 | // degsplit(pCopy(g),pot,g1,g0); |
---|
188 | // div_by_x_power_n(g1,pot); |
---|
189 | |
---|
190 | // //p00 |
---|
191 | // //p11 |
---|
192 | // poly p00=unifastmult(f0,g0); |
---|
193 | // poly p11=unifastmult(f1,g1); |
---|
194 | |
---|
195 | |
---|
196 | |
---|
197 | |
---|
198 | // //eat up f0,f1,g0,g1 |
---|
199 | // poly pbig=unifastmult(pAdd(f0,f1),pAdd(g0,g1)); |
---|
200 | // poly factor=pOne();//pCopy(erg_mult); |
---|
201 | // pSetExp(factor,1,n); |
---|
202 | // pseudo_len=0; |
---|
203 | // kBucket_Add_q(erg_bucket,ppMult_mm(p11,factor),&pseudo_len); |
---|
204 | // pseudo_len=0; |
---|
205 | // kBucket_Add_q(erg_bucket,pCopy(p00),&pseudo_len); |
---|
206 | // pSetExp(factor,1,pot); |
---|
207 | |
---|
208 | // //eat up pbig |
---|
209 | // pseudo_len=0; |
---|
210 | // kBucket_Add_q(erg_bucket,pMult_mm(pbig,factor),&pseudo_len); |
---|
211 | // pseudo_len=0; |
---|
212 | // //eat up p00 |
---|
213 | // kBucket_Add_q(erg_bucket,pMult_mm(pNeg(p00),factor),&pseudo_len); |
---|
214 | // pseudo_len=0; |
---|
215 | // //eat up p11 |
---|
216 | // kBucket_Add_q(erg_bucket,pMult_mm(pNeg(p11),factor),&pseudo_len); |
---|
217 | |
---|
218 | |
---|
219 | // pseudo_len=0; |
---|
220 | |
---|
221 | |
---|
222 | // pDelete(&factor); |
---|
223 | |
---|
224 | // int len=0; |
---|
225 | // poly erg=NULL; |
---|
226 | // kBucketClear(erg_bucket,&erg,&len); |
---|
227 | // kBucketDestroy(&erg_bucket); |
---|
228 | |
---|
229 | // return erg; |
---|
230 | // } |
---|
231 | |
---|
232 | static inline int max(int a, int b){ |
---|
233 | return (a>b)? a:b; |
---|
234 | } |
---|
235 | static inline int min(int a, int b){ |
---|
236 | return (a>b)? b:a; |
---|
237 | } |
---|
238 | poly unifastmult(poly f,poly g, ring r){ |
---|
239 | int vn=1; |
---|
240 | if((f==NULL)||(g==NULL)) return NULL; |
---|
241 | int df=p_GetExp(f,vn,r); |
---|
242 | int dg=p_GetExp(g,vn,r); |
---|
243 | if ((df==0)||(dg==0)) |
---|
244 | return pp_Mult_qq(f,g,r); |
---|
245 | if (df*dg<100) |
---|
246 | return pp_Mult_qq(f,g,r); |
---|
247 | // if (df*dg>10000) |
---|
248 | // return |
---|
249 | // do_unifastmult_buckets(f,g); |
---|
250 | //else |
---|
251 | return do_unifastmult(f,df,g,dg,vn,unifastmult,r); |
---|
252 | |
---|
253 | } |
---|
254 | |
---|
255 | poly multifastmult(poly f, poly g, ring r){ |
---|
256 | mults++; |
---|
257 | if((f==NULL)||(g==NULL)) return NULL; |
---|
258 | if (pLength(f)*pLength(g)<100) |
---|
259 | return pp_Mult_qq(f,g,r); |
---|
260 | //find vn |
---|
261 | //determine df,dg simultaneously |
---|
262 | int i; |
---|
263 | int can_i=-1; |
---|
264 | int can_df=0; |
---|
265 | int can_dg=0; |
---|
266 | int can_crit=0; |
---|
267 | for(i=1;i<=rVar(r);i++){ |
---|
268 | poly p; |
---|
269 | int df=0; |
---|
270 | int dg=0; |
---|
271 | //max min max Strategie |
---|
272 | p=f; |
---|
273 | while(p){ |
---|
274 | df=max(df,p_GetExp(p,i,r)); |
---|
275 | p=pNext(p); |
---|
276 | } |
---|
277 | if(df>can_crit){ |
---|
278 | p=g; |
---|
279 | while(p){ |
---|
280 | dg=max(dg,p_GetExp(p,i,r)); |
---|
281 | p=pNext(p); |
---|
282 | } |
---|
283 | int crit=min(df,dg); |
---|
284 | if (crit>can_crit){ |
---|
285 | can_crit=crit; |
---|
286 | can_i=i; |
---|
287 | can_df=df; |
---|
288 | can_dg=dg; |
---|
289 | } |
---|
290 | } |
---|
291 | } |
---|
292 | if(can_crit==0) |
---|
293 | return pp_Mult_qq(f,g,r); |
---|
294 | else |
---|
295 | { |
---|
296 | poly erg=do_unifastmult(f,can_df,g,can_dg,can_i,multifastmult,r); |
---|
297 | p_Normalize(erg,r); |
---|
298 | return(erg); |
---|
299 | } |
---|
300 | } |
---|