source: git/kernel/fast_mult.cc @ a82c308

spielwiese
Last change on this file since a82c308 was 762407, checked in by Oleksandr Motsak <motsak@…>, 12 years ago
config.h is for sources files only FIX: config.h should only be used by source (not from inside kernel/mod2.h!) NOTE: each source file should better include mod2.h right after config.h, while headers should better not include mod2.h.
  • Property mode set to 100644
File size: 13.2 KB
Line 
1/****************************************
2*  Computer Algebra System SINGULAR     *
3****************************************/
4/* $Id$ */
5#include "config.h"
6#include "mod2.h"
7#include <polys/monomials/ring.h>
8#include <kernel/fast_mult.h>
9#include <polys/kbuckets.h>
10#include <kernel/febase.h>
11
12typedef poly fastmultrec(poly f, poly g, ring r);
13static const int pass_option=1;
14static int mults=0;
15int Mults()
16{
17  return mults;
18}
19static void degsplit(poly p,int n,poly &p1,poly&p2, int vn, ring r)
20{
21  poly erg1_i, erg2_i;
22  erg1_i=NULL;
23  erg2_i=NULL;
24  while(p)
25  {
26    if(p_GetExp(p,vn,r)>=n)
27    {
28      if (p1==NULL)
29      {
30        p1=p;
31      }
32      else
33      {
34        pNext(erg1_i)=p;
35      }
36      erg1_i=p;
37    }
38    else
39    {
40      if (p2==NULL)
41      {
42        p2=p;
43      }
44      else
45      {
46        pNext(erg2_i)=p;
47      }
48      erg2_i=p;
49    }
50    p=pNext(p);
51  }
52  if(erg2_i)
53  {
54    pNext(erg2_i)=NULL;
55  }
56  if (erg1_i)
57  {
58    pNext(erg1_i)=NULL;
59  }
60
61}
62static void div_by_x_power_n(poly p, int n, int vn, ring r)
63{
64  while(p)
65  {
66    assume(p_GetExp(p,vn,r)>=n);
67    int e=p_GetExp(p,vn,r);
68    p_SetExp(p,vn,e-n,r);
69    p=pNext(p);
70  }
71}
72
73static poly do_unifastmult(poly f,int df,poly g,int dg, int vn, fastmultrec rec, ring r)
74{
75  int n=1;
76  if ((f==NULL)||(g==NULL)) return NULL;
77  //int df=pGetExp(f,vn);//pFDeg(f);
78  //  int dg=pGetExp(g,vn);//pFDeg(g);
79
80  int dm;
81  if(df>dg)
82  {
83    dm=df;
84  }
85  else
86  {
87    dm=dg;
88  }
89  while(n<=dm)
90    {
91      n*=2;
92    }
93  if(n==1)
94  {
95    return(pp_Mult_qq(f,g,r));
96  }
97
98  int pot=n/2;
99  assume(pot*2==n);
100
101
102  //splitting
103  poly f1=NULL;
104  poly f0=NULL;//f-(x^(pot)*F1);
105  degsplit(p_Copy(f,r),pot,f1,f0,vn,r);
106  div_by_x_power_n(f1,pot,vn,r);
107
108  poly g1=NULL;
109  poly g0=NULL;
110  degsplit(p_Copy(g,r),pot,g1,g0,vn,r);
111  div_by_x_power_n(g1,pot,vn,r);
112
113  //p00, p11
114  poly p00=rec(f0,g0,r);//unifastmult(f0,g0);
115  poly p11=rec(f1,g1,r);
116
117  //construct erg, factor
118  poly erg=NULL;
119  poly factor=p_ISet(1,r);
120
121  p_SetExp(factor,vn,n,r);
122  erg=pp_Mult_mm(p11,factor,r);
123  erg=p_Add_q(erg,p_Copy(p00,r),r);
124
125
126
127
128
129  if((f1!=NULL) &&(f0!=NULL) &&(g0!=NULL) && (g1!=NULL))
130  {
131    //if(true){
132    //eat up f0,f1,g0,g1
133    poly s1=p_Add_q(f0,f1,r);
134    poly s2=p_Add_q(g0,g1,r);
135    poly pbig=rec(s1,s2,r);
136    p_Delete(&s1,r);
137    p_Delete(&s2,r);
138
139
140    //eat up pbig
141    poly sum=pbig;
142    p_SetExp(factor,vn,pot,r);
143
144    //eat up p00
145    sum=p_Add_q(sum,p_Neg(p00,r),r);
146
147    //eat up p11
148    sum=p_Add_q(sum,p_Neg(p11,r),r);
149
150
151    sum=p_Mult_mm(sum,factor,r);
152
153
154    //eat up sum
155    erg=p_Add_q(sum,erg,r);
156  }
157  else
158  {
159    //eat up f0,f1,g0,g1
160    poly s1=rec(f0,g1,r);
161    poly s2=rec(g0,f1,r);
162    p_SetExp(factor,vn,pot,r);
163    poly h=p_Mult_mm(((s1!=NULL)?s1:s2),factor,r);
164    p_Delete(&f1,r);
165    p_Delete(&f0,r);
166    p_Delete(&g0,r);
167    p_Delete(&g1,r);
168    p_Delete(&p00,r);
169    p_Delete(&p11,r);
170    erg=p_Add_q(erg,h,r);
171  }
172
173
174  p_Delete(&factor,r);
175
176
177
178  return(erg);
179}
180
181// poly do_unifastmult_buckets(poly f,poly g){
182
183
184
185
186//   int n=1;
187//   if ((f==NULL)||(g==NULL)) return NULL;
188//   int df=pGetExp(f,1);//pFDeg(f);
189//     int dg=pGetExp(g,1);//pFDeg(g);
190
191//   int dm;
192//   if(df>dg){
193//     dm=df;
194//   }else{
195//     dm=dg;
196//   }
197//   while(n<=dm)
198//     {
199//       n*=2;
200//     }
201//   int pseudo_len=0;
202//   if(n==1){
203//     return ppMult_qq(f,g);
204
205//   }
206//   kBucket_pt erg_bucket= kBucketCreate(currRing);
207//   kBucketInit(erg_bucket,NULL,0 /*pLength(P.p)*/);
208
209//   int pot=n/2;
210//   assume(pot*2==n);
211
212
213//   //splitting
214//   poly f1=NULL;
215//   poly f0=NULL;//f-(x^(pot)*F1);
216//   degsplit(pCopy(f),pot,f1,f0);
217//   div_by_x_power_n(f1,pot);
218//   poly g1=NULL;
219//   poly g0=NULL;
220//   degsplit(pCopy(g),pot,g1,g0);
221//   div_by_x_power_n(g1,pot);
222
223//   //p00
224//   //p11
225//   poly p00=unifastmult(f0,g0);
226//   poly p11=unifastmult(f1,g1);
227
228
229
230
231//   //eat up f0,f1,g0,g1
232//   poly pbig=unifastmult(pAdd(f0,f1),pAdd(g0,g1));
233//   poly factor=pOne();//pCopy(erg_mult);
234//   pSetExp(factor,1,n);
235//   pseudo_len=0;
236//   kBucket_Add_q(erg_bucket,ppMult_mm(p11,factor),&pseudo_len);
237//   pseudo_len=0;
238//   kBucket_Add_q(erg_bucket,pCopy(p00),&pseudo_len);
239//   pSetExp(factor,1,pot);
240
241//   //eat up pbig
242//   pseudo_len=0;
243//   kBucket_Add_q(erg_bucket,pMult_mm(pbig,factor),&pseudo_len);
244//   pseudo_len=0;
245//   //eat up p00
246//   kBucket_Add_q(erg_bucket,pMult_mm(pNeg(p00),factor),&pseudo_len);
247//   pseudo_len=0;
248//   //eat up p11
249//   kBucket_Add_q(erg_bucket,pMult_mm(pNeg(p11),factor),&pseudo_len);
250
251
252//   pseudo_len=0;
253
254
255//   pDelete(&factor);
256
257//   int len=0;
258//   poly erg=NULL;
259//   kBucketClear(erg_bucket,&erg,&len);
260//   kBucketDestroy(&erg_bucket);
261
262//   return erg;
263// }
264
265static inline int max(int a, int b)
266{
267  return (a>b)? a:b;
268}
269static inline int min(int a, int b)
270{
271  return (a>b)? b:a;
272}
273poly unifastmult(poly f,poly g, ring r)
274{
275  int vn=1;
276  if((f==NULL)||(g==NULL)) return NULL;
277  int df=p_GetExp(f,vn,r);
278  int dg=p_GetExp(g,vn,r);
279  if ((df==0)||(dg==0))
280    return pp_Mult_qq(f,g,r);
281  if (df*dg<100)
282    return pp_Mult_qq(f,g,r);
283  // if (df*dg>10000)
284  //  return
285  //    do_unifastmult_buckets(f,g);
286  //else
287  return do_unifastmult(f,df,g,dg,vn,unifastmult,r);
288
289}
290
291poly multifastmult(poly f, poly g, ring r)
292{
293  mults++;
294  if((f==NULL)||(g==NULL)) return NULL;
295  if (pLength(f)*pLength(g)<100)
296    return pp_Mult_qq(f,g,r);
297  //find vn
298  //determine df,dg simultaneously
299  int i;
300  int can_i=-1;
301  int can_df=0;
302  int can_dg=0;
303  int can_crit=0;
304  for(i=1;i<=rVar(r);i++)
305  {
306    poly p;
307    int df=0;
308    int dg=0;
309    //max min max Strategie
310    p=f;
311    while(p)
312    {
313      df=max(df,p_GetExp(p,i,r));
314      p=pNext(p);
315    }
316    if(df>can_crit)
317    {
318      p=g;
319      while(p)
320      {
321        dg=max(dg,p_GetExp(p,i,r));
322        p=pNext(p);
323      }
324      int crit=min(df,dg);
325      if (crit>can_crit)
326      {
327        can_crit=crit;
328        can_i=i;
329        can_df=df;
330        can_dg=dg;
331      }
332    }
333  }
334  if(can_crit==0)
335    return pp_Mult_qq(f,g,r);
336  else
337    {
338      poly erg=do_unifastmult(f,can_df,g,can_dg,can_i,multifastmult,r);
339      p_Normalize(erg,r);
340      return(erg);
341    }
342}
343poly pFastPower(poly f, int n, ring r)
344{
345  if (n==1) return f;
346  if (n==0) return p_ISet(1,r);
347  assume(n>=0);
348  int i_max=1;
349  int pot_max=0;
350  while(i_max*2<=n)
351  {
352    i_max*=2;
353    pot_max++;
354  }
355  int field_size=pot_max+1;
356  int* int_pot_array=(int*) omAlloc(field_size*sizeof(int));
357  poly* pot_array=(poly*) omAlloc(field_size*sizeof(poly));
358  int i;
359  int pot=1;
360  //initializing int_pot
361  for(i=0;i<field_size;i++)
362  {
363    int_pot_array[i]=pot;
364    pot*=2;
365  }
366  //calculating pot_array
367  pot_array[0]=f; //do not delete it
368  for(i=1;i<field_size;i++)
369  {
370    poly p=pot_array[i-1];
371    if(rVar(r)==1)
372      pot_array[i]=multifastmult(p,p,r);
373    else
374      pot_array[i]=pp_Mult_qq(p,p,r);
375  }
376
377
378
379  int work_n=n;
380  assume(work_n>=int_pot_array[field_size-1]);
381  poly erg=p_ISet(1,r);
382
383
384  //forward maybe faster, later
385  // for(i=field_size-1;i>=0;i--){
386
387//       assume(work_n<2*int_pot_array[i]);
388//       if(int_pot_array[i]<=work_n){
389//         work_n-=int_pot_array[i];
390//         poly prod=multifastmult(erg,pot_array[i],r);
391//         pDelete(&erg);
392//         erg=prod;
393//       }
394
395//       if(i!=0) pDelete(&pot_array[i]);
396//   }
397
398
399  for(i=field_size-1;i>=0;i--)
400  {
401
402      assume(work_n<2*int_pot_array[i]);
403      if(int_pot_array[i]<=work_n)
404      {
405        work_n-=int_pot_array[i];
406        int_pot_array[i]=1;
407      }
408      else int_pot_array[i]=0;
409
410  }
411  for(i=0;i<field_size;i++)
412  {
413    if(int_pot_array[i]==1)
414    {
415      poly prod;
416      if(rVar(r)==1)
417        prod=multifastmult(erg,pot_array[i],r);
418      else
419        prod=pp_Mult_qq(erg,pot_array[i],r);
420      pDelete(&erg);
421      erg=prod;
422    }
423    if(i!=0) pDelete(&pot_array[i]);
424  }
425  //free res
426  omfree(pot_array);
427  omfree(int_pot_array);
428  return erg;
429}
430static omBin lm_bin=NULL;
431/*3
432* compute for monomials p*q
433* destroys p, keeps q
434*/
435static void p_MonMultMB(poly p, poly q,ring r)
436{
437  number x, y;
438  // int i;
439
440  y = p_GetCoeff(p,r);
441  x = n_Mult(y,pGetCoeff(q),r->cf);
442  n_Delete(&y,r->cf);
443  p_SetCoeff0(p,x,r);
444  //for (i=(currRing->N); i!=0; i--)
445  //{
446  //  pAddExp(p,i, pGetExp(q,i));
447  //}
448  //p->Order += q->Order;
449  p_ExpVectorAdd(p,q,r);
450}
451/*3
452* compute for monomials p*q
453* keeps p, q
454* uses bin only available in MCPower
455*/
456static poly p_MonMultCMB(poly p, poly q, ring r)
457{
458  number x;
459  poly res = p_Init(r,lm_bin);
460
461  x = n_Mult(p_GetCoeff(p,r),p_GetCoeff(q,r),r->cf);
462  p_SetCoeff0(res,x,r);
463  p_ExpVectorSum(res,p, q,r);
464  return res;
465}
466static poly p_MonPowerMB(poly p, int exp, ring r)
467{
468  int i;
469
470  if(!n_IsOne(p_GetCoeff(p,r),r->cf))
471  {
472    number x, y;
473    y = p_GetCoeff(p,r);
474    n_Power(y,exp,&x,r->cf);
475    n_Delete(&y,r->cf);
476    p_SetCoeff0(p,x,r);
477  }
478  for (i=rVar(r); i!=0; i--)
479  {
480    p_MultExp(p,i, exp,r);
481  }
482  p_Setm(p,r);
483  return p;
484}
485static void buildTermAndAdd(int n,number* facult,poly* f_terms,int* exp,int f_len,kBucket_pt erg_bucket,ring r, number coef, poly & zw, poly tmp, poly** term_pot){
486
487  int i;
488  //  poly term=p_Init(r);
489
490   //  number denom=n_Init(1,r);
491//   for(i=0;i<f_len;i++){
492//     if(exp[i]!=0){
493//       number trash=denom;
494//       denom=n_Mult(denom,facult[exp[i]],r);
495//       n_Delete(&trash,r);
496//     }
497
498//   }
499//   number coef=n_IntDiv(facult[n],denom,r);   //right function here?
500//   n_Delete(&denom,r);
501//   poly erg=p_NSet(coef,r);
502  poly erg=p_Init(r,lm_bin);
503  p_SetCoeff0(erg, coef,r);
504  //p_NSet(n_Copy(coef,r),r);
505  for(i=0;i<f_len;i++){
506    if(exp[i]!=0){
507      ///poly term=p_Copy(f_terms[i],r);
508      poly term=term_pot[i][exp[i]];
509        //tmp;
510        //p_ExpVectorCopy(term,f_terms[i],r);
511        //p_SetCoeff(term, n_Copy(p_GetCoeff(f_terms[i],r),r),r);
512
513      //term->next=NULL;
514
515      //p_MonPowerMB(term, exp[i],r);
516      p_MonMultMB(erg,term,r);
517      //p_Delete(&term,r);
518    }
519
520  }
521  zw=erg;
522}
523
524
525
526static void MC_iterate(poly f, int n, ring r, int f_len,number* facult, int* exp,poly* f_terms,kBucket_pt erg_bucket,int pos,int sum, number coef, poly & zw, poly tmp, poly** term_pot){
527  int i;
528
529  if (pos<f_len-1)
530  {
531    poly zw_l=NULL;
532    number new_coef;
533    for(i=0;i<=n-sum;i++)
534    {
535      exp[pos]=i;
536      if(i==0)
537      {
538        new_coef=n_Copy(coef,r->cf);
539      }
540      else
541      {
542        number old=new_coef;
543        number old_rest=n_Init(n-sum-(i-1),r->cf);
544        new_coef=n_Mult(new_coef,old_rest,r->cf);
545        n_Delete(&old_rest,r->cf);
546        n_Delete(&old,r->cf);
547        number i_number=n_Init(i,r->cf);
548        old=new_coef;
549        new_coef=n_IntDiv(new_coef,i_number,r->cf);
550        n_Delete(&old,r->cf);
551        n_Delete(&i_number,r->cf);
552      }
553      //new_coef is
554      //(n                          )
555      //(exp[0]..exp[pos] 0 0 0 rest)
556      poly zw_real=NULL;
557      MC_iterate(f, n, r, f_len,facult, exp,f_terms,erg_bucket,pos+1,sum+i,new_coef,zw_real,tmp,term_pot);
558      if (pos==f_len-2)
559      {
560        //get first small polys
561
562        zw_real->next=zw_l;
563        zw_l=zw_real;
564      }
565      //n_Delete(& new_coef,r->cf);
566    }
567    n_Delete(&new_coef,r->cf);
568    if (pos==f_len-2)
569    {
570      int len=n-sum+1;
571      kBucket_Add_q(erg_bucket,zw_l,&len);
572    }
573    return;
574  }
575  if(pos==f_len-1)
576  {
577    i=n-sum;
578    exp[pos]=i;
579    number new_coef=n_Copy(coef,r->cf);//n_IntDiv(coef,facult[i],r); //really consumed???????
580    buildTermAndAdd(n,facult,f_terms,exp,f_len,erg_bucket,r, new_coef,zw, tmp,term_pot);
581    // n_Delete(& new_coef,r);
582  }
583  assume(pos<=f_len-1);
584}
585poly pFastPowerMC(poly f, int n, ring r)
586{
587  //only char=0
588
589  if(rChar(r)!=0)
590    Werror("Char not 0, pFastPowerMC not implemented for this case");
591  if (n<=1)
592    Werror("not implemented for so small n, recursion fails");//should be length(f)
593   if (pLength(f)<=1)
594    Werror("not implemented for so small lenght of f, recursion fails");
595  //  number null_number=n_Init(0,r);
596  number* facult=(number*) omAlloc((n+1)*sizeof(number));
597  facult[0]=n_Init(1,r->cf);
598  int i;
599  for(i=1;i<=n;i++)
600  {
601    number this_n=n_Init(i,r->cf);
602    facult[i]=n_Mult(this_n,facult[i-1],r->cf);
603    n_Delete(&this_n,r->cf);
604  }
605
606  lm_bin=omGetSpecBin(POLYSIZE + (r->ExpL_Size)*sizeof(long));
607
608  kBucket_pt erg_bucket= kBucketCreate(currRing);
609  kBucketInit(erg_bucket,NULL,0);
610  const int f_len=pLength(f);
611  int* exp=(int*)omAlloc(f_len*sizeof(int));
612  //poly f_terms[f_len];
613  poly* f_terms=(poly*)omAlloc(f_len*sizeof(poly));
614  poly** term_potences=(poly**) omAlloc(f_len*sizeof(poly*));
615
616  poly f_iter=f;
617  for(i=0;i<f_len;i++)
618  {
619    f_terms[i]=f_iter;
620    f_iter=pNext(f_iter);
621  }
622  for(i=0;i<f_len;i++)
623  {
624    term_potences[i]=(poly*)omAlloc((n+1)*sizeof(poly));
625    term_potences[i][0]=p_ISet(1,r);
626    int j;
627    for(j=1;j<=n;j++){
628      term_potences[i][j]=p_MonMultCMB(f_terms[i],term_potences[i][j-1],r);
629    }
630  }
631  assume(f_iter==NULL);
632  poly zw=NULL;
633  poly tmp=p_Init(r);
634  number one=n_Init(1,r->cf);
635  MC_iterate(f,n,r,f_len,&facult[0], &exp[0], &f_terms[0],erg_bucket,0,0,one/*facult[n]*/,zw,tmp, term_potences);
636
637
638  n_Delete(&one,r->cf);
639
640
641
642  //free res
643
644  //free facult
645  for(i=0;i<=n;i++)
646  {
647    n_Delete(&facult[i],r->cf);
648  }
649  int i2;
650  for (i=0;i<f_len;i++)
651  {
652    for(i2=0;i2<=n;i2++)
653    {
654      p_Delete(&term_potences[i][i2],r);
655    }
656    omfree(term_potences[i]);
657
658  }
659  omfree(term_potences);
660  p_Delete(&tmp,r);
661  omfree(exp);
662  omfree(facult);
663  omfree(f_terms);
664  int len=0;
665  poly erg;
666  kBucketClear(erg_bucket,&erg, &len);
667  kBucketDestroy(&erg_bucket);
668  omUnGetSpecBin(&lm_bin);
669  return erg;
670}
Note: See TracBrowser for help on using the repository browser.