source: git/Singular/tgb.cc @ bb816a

spielwiese
Last change on this file since bb816a was bb816a, checked in by Michael Brickenstein <bricken@…>, 20 years ago
*bricken: adjusted to modifying nNeg git-svn-id: file:///usr/local/Singular/svn/trunk@7549 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 110.5 KB
Line 
1
2// #define OM_CHECK 3
3// #define OM_TRACK 5
4// #define OM_KEEP  1
5// TODO:
6//       deg -> poly_crit
7//       multiple rings
8//       shorten_tails und dessen Aufrufe pruefen wlength!!!
9//       calculating with formal sums
10//       try to create spolys as formal sums
11
12#include "tgb.h"
13static const int bundle_size=100;
14#if 1
15static omBin lm_bin=NULL;
16static inline poly p_Init_Special(const ring r)
17{
18  return p_Init(r,lm_bin);
19}
20static inline poly pOne_Special(const ring r=currRing)
21{
22  poly rc = p_Init_Special(r);
23  pSetCoeff0(rc,r->cf->nInit(1));
24  return rc;
25}
26// zum Initialiseren: in t_rep_gb plazieren:
27
28#endif
29#define LEN_VAR1
30#define degbound(p) assume(pTotaldegree(p)<10)
31//#define inDebug(p) assume((debug_Ideal==NULL)||(kNF(debug_Ideal,NULL,p,0,0)==0))
32#ifdef LEN_VAR1
33// erste Variante: Laenge: Anzahl der Monome
34int pSLength(poly p, int l) {
35  return l; }
36int kSBucketLength(kBucket* bucket) {return bucket_guess(bucket);}
37#endif
38
39#ifdef LEN_VAR2
40// 2. Variante: Laenge: Platz fuer die Koeff.
41int pSLength(poly p,int l)
42{
43  int s=0;
44  while (p!=NULL) { s+=nSize(pGetCoeff(p));pIter(p); }
45  return s;
46}
47int kSBucketLength(kBucket* b)
48{
49  int s=0;
50  int i;
51  for (i=MAX_BUCKET;i>=0;i--)
52  {
53    s+=pSLength(b->buckets[i],0);
54  }
55  return s;
56}
57#endif
58
59#ifdef LEN_VAR3
60// 3.Variante: Laenge: Platz fuer Leitk * Monomanzahl
61int pSLength(poly p,int l)
62{
63  int c=nSize(pGetCoeff(p));
64  return c*l /*pLength(p)*/;
65}
66int kSBucketLength(kBucket* b)
67{
68  int s=0;
69  int c=nSize(pGetCoeff(kBucketGetLm(b)))+1;
70  int i;
71  for (i=MAX_BUCKET;i>0;i--)
72  {
73    s+=b->buckets_length[i] /*pLength(b->buckets[i])*/;
74  }
75  return s*c;
76}
77#endif
78
79#ifdef LEN_VAR4
80// 4.Variante: Laenge: Platz fuer Leitk * (1+Platz fuer andere Koeff.)
81int pSLength(poly p, int l)
82{
83  int s=1;
84  int c=nSize(pGetCoeff(p));
85  pIter(p);
86  while (p!=NULL) { s+=nSize(pGetCoeff(p));pIter(p); }
87  return s*c;
88}
89int kSBucketLength(kBucket* b)
90{
91  int s=1;
92  int c=nSize(pGetCoeff(kBucketGetLm(b)));
93  int i;
94  for (i=MAX_BUCKET;i>0;i--)
95  {
96    if(b->buckets[i]==NULL) continue;
97    s+=pSLength(b->buckets[i],0);
98  }
99  return s*c;
100}
101#endif
102static void finalize_reduction_step(reduction_step* r){
103  delete r;
104}
105static int LObject_better_gen(const void* ap, const void* bp)
106{
107  LObject* a=*(LObject**)ap;
108  LObject* b=*(LObject**)bp;
109  return(pLmCmp(a->p,b->p));
110}
111static int red_object_better_gen(const void* ap, const void* bp)
112{
113
114
115  return(pLmCmp(((red_object*) ap)->p,((red_object*) bp)->p));
116}
117static int monom_poly_crit(const void* ap1, const void* ap2){
118  monom_poly* p1;
119  monom_poly* p2;
120  p1=((monom_poly*) ap1);
121  p2=((monom_poly*)ap2);
122  if(((unsigned long) p1->f)>((unsigned long) p2->f)) return 1;
123  if(((unsigned long) p1->f)<((unsigned long)p2->f)) return -1; 
124
125  return pLmCmp(p1->m,p2->m);
126 
127}
128static int pLmCmp_func(const void* ap1, const void* ap2){
129    poly p1,p2;
130  p1=*((poly*) ap1);
131  p2=*((poly*)ap2);
132
133  return pLmCmp(p1,p2);
134}
135static int pLmCmp_func_inverted(const void* ap1, const void* ap2){
136    poly p1,p2;
137  p1=*((poly*) ap1);
138  p2=*((poly*)ap2);
139
140  return -pLmCmp(p1,p2);
141}
142
143static int pair_better_gen2(const void* ap,const void* bp){
144  return(-pair_better_gen(ap,bp));
145}
146static int kFindDivisibleByInS_easy(kStrategy strat,const red_object & obj){
147  int i;
148  long not_sev=~obj.sev;
149  poly p=obj.p;
150  for(i=0;i<=strat->sl;i++){
151    if (pLmShortDivisibleBy(strat->S[i],strat->sevS[i],p,not_sev))
152      return i;
153  }
154  return -1;
155}
156static int kFindDivisibleByInS_easy(kStrategy strat,poly p, long sev){
157  int i;
158  long not_sev=~sev;
159  for(i=0;i<=strat->sl;i++){
160    if (pLmShortDivisibleBy(strat->S[i],strat->sevS[i],p,not_sev))
161      return i;
162  }
163  return -1;
164}
165static int posInPairs (sorted_pair_node**  p, int pn, sorted_pair_node* qe,calc_dat* c,int an=0)
166{
167  if(pn==0) return 0;
168
169  int length=pn-1;
170  int i;
171  //int an = 0;
172  int en= length;
173
174  if (pair_better(qe,p[en],c))
175    return length+1;
176
177  while(1)
178    {
179      //if (an >= en-1)
180      if(en-1<=an)
181      {
182        if (pair_better(p[an],qe,c)) return an;
183        return en;
184      }
185      i=(an+en) / 2;
186        if (pair_better(p[i],qe,c))
187          en=i;
188      else an=i;
189    }
190}
191static int posInPolys (poly*  p, int pn, poly qe,calc_dat* c)
192{
193  if(pn==0) return 0;
194
195  int length=pn-1;
196  int i;
197  int an = 0;
198  int en= length;
199
200  if (pLmCmp(qe,p[en])==1)
201    return length+1;
202
203  while(1)
204    {
205      //if (an >= en-1)
206      if(en-1<=an)
207      {
208        if (pLmCmp(p[an],qe)==1) return an;
209        return en;
210      }
211      i=(an+en) / 2;
212        if (pLmCmp(p[i],qe)==1)
213          en=i;
214      else an=i;
215    }
216}
217static int posInMonomPolys (monom_poly*  p, int pn, monom_poly & qe,calc_dat* c)
218{
219  if(pn==0) return 0;
220
221  int length=pn-1;
222  int i;
223  int an = 0;
224  int en= length;
225
226  if (monom_poly_crit(&qe,&p[en])==1)
227    return length+1;
228
229  while(1)
230    {
231      //if (an >= en-1)
232      if(en-1<=an)
233      {
234        if (monom_poly_crit(&p[an],&qe)==1) return an;
235        return en;
236      }
237      i=(an+en) / 2;
238        if (monom_poly_crit(&p[i],&qe)==1)
239          en=i;
240      else an=i;
241    }
242}
243static BOOLEAN  ascending(int* i,int top){
244  if(top<1) return TRUE;
245  if(i[top]<i[top-1]) return FALSE;
246  return ascending(i,top-1);
247}
248
249sorted_pair_node**  merge(sorted_pair_node** p, int pn,sorted_pair_node **q, int qn,calc_dat* c){
250  int i;
251  int* a= (int*) omalloc(qn*sizeof(int));
252//   int mc;
253//   PrintS("Debug\n");
254//   for(mc=0;mc<qn;mc++)
255// {
256
257//     wrp(q[mc]->lcm_of_lm);
258//     PrintS("\n");
259// }
260//    PrintS("Debug they are in\n");
261//   for(mc=0;mc<pn;mc++)
262// {
263
264//     wrp(p[mc]->lcm_of_lm);
265//     PrintS("\n");
266// }
267  int lastpos=0;
268  for(i=0;i<qn;i++){
269    lastpos=posInPairs(p,pn,q[i],c, max(lastpos-1,0));
270    //   cout<<lastpos<<"\n";
271    a[i]=lastpos;
272
273  }
274  if((pn+qn)>c->max_pairs){
275    p=(sorted_pair_node**) omrealloc(p,2*(pn+qn)*sizeof(sorted_pair_node*));
276    c->max_pairs=2*(pn+qn);
277  }
278  for(i=qn-1;i>=0;i--){
279    size_t size;
280    if(qn-1>i)
281      size=(a[i+1]-a[i])*sizeof(sorted_pair_node*);
282    else
283      size=(pn-a[i])*sizeof(sorted_pair_node*); //as indices begin with 0
284    memmove (p+a[i]+(1+i), p+a[i], size);
285    p[a[i]+i]=q[i];
286  }
287  omfree(a);
288  return p;
289}
290
291
292static BOOLEAN trivial_syzygie(int pos1,int pos2,poly bound,calc_dat* c){
293
294
295  poly p1=c->S->m[pos1];
296  poly p2=c->S->m[pos2];
297  ring r=c->r;
298 
299
300  if (pGetComp(p1) > 0 || pGetComp(p2) > 0)
301    return FALSE;
302  int i = 1;
303  poly m=NULL;
304  poly gcd1=c->gcd_of_terms[pos1];
305  poly gcd2=c->gcd_of_terms[pos2];
306 
307  if((gcd1!=NULL) && (gcd2!=NULL)) 
308    {
309      gcd1->next=gcd2; //may ordered incorrect
310      poly m=gcd_of_terms(gcd1,c->r);
311      gcd1->next=NULL;
312     
313    } 
314
315  if (m==NULL) 
316  {
317     loop
318      {
319        if (pGetExp(p1, i)+ pGetExp(p2, i) > pGetExp(bound,i))   return FALSE;
320        if (i == pVariables){
321          //PrintS("trivial");
322          return TRUE;
323        }
324        i++;
325      }
326  }
327  else 
328  {
329    loop
330      {
331        if (pGetExp(p1, i)-pGetExp(m,i) + pGetExp(p2, i) > pGetExp(bound,i))   return FALSE;
332        if (i == pVariables){
333          pDelete(&m);
334          //PrintS("trivial");
335          return TRUE;
336        }
337        i++;
338      }
339  }
340
341 
342
343 
344}
345
346///returns position sets w as weight
347int find_best(red_object* r,int l, int u, int &w, calc_dat* c){
348  int best=l;
349  int i;
350  w=r[l].guess_quality(c);
351  for(i=l+1;i<=u;i++){
352    int w2=r[i].guess_quality(c);
353    if(w2<w){
354      w=w2;
355      best=i;
356    }
357   
358  }
359 return best;
360}
361
362#if 0 
363int find_best(red_object* r,int l, int u, int &w, calc_dat* c){
364
365  int sz=u-l+1;
366  int n=sz/10+1;
367  int filled=0;
368  int* indizes=(int*) omalloc(n*sizeof(int));
369  int* weight=(int*) omalloc(n*sizeof(int));
370  int worst=-1;
371  int i; 
372  for(i=l;i<=u;i++){
373    int q=r[i].guess_quality(c);
374    if ((filled<n)||(q<worst)){
375      if(filled<n){
376        worst=max(q,worst);
377        indizes[filled]=i;
378        weight[filled]=q;
379        filled++;
380      }
381    }
382    else{
383      int j;
384      for(j=0;j<filled;j++){
385        if (worst==weight[j]){
386          weight[j]=q;
387          indizes[j]=i;
388        }
389      }
390      worst=-1;
391      for(j=0;j<filled;j++){
392        if (worst<weight[j]){
393          worst=weight[j];
394        }
395      }
396    }
397  }
398  assume(filled==n);
399  int pos=0;
400
401  for(i=0;i<filled;i++){ 
402    r[indizes[i]].canonicalize();
403    weight[i]=r[indizes[i]].guess_quality(c);
404    if(weight[i]<weight[pos]) pos=i;
405  }
406  w=weight[pos];
407  pos=indizes[pos];
408
409  omfree(indizes);
410  omfree(weight);
411
412  assume(w==r[pos].guess_quality(c));
413  assume(l<=pos);
414  assume(u>=pos);
415  return pos;
416 
417}
418
419#endif
420void red_object::canonicalize(){
421  kBucketCanonicalize(bucket);
422  if(sum)
423    kBucketCanonicalize(sum->ac->bucket);
424 
425}
426BOOLEAN good_has_t_rep(int i, int j,calc_dat* c){
427  assume(i>=0);
428    assume(j>=0);
429  if (has_t_rep(i,j,c)) return TRUE;
430  //poly lm=pOne();
431  assume (c->tmp_lm!=NULL);
432  poly lm=c->tmp_lm;
433
434  pLcm(c->S->m[i], c->S->m[j], lm);
435  pSetm(lm);
436  assume(lm!=NULL);
437  //int deciding_deg= pTotaldegree(lm);
438  int* i_con =make_connections(i,j,lm,c);
439  //p_Delete(&lm,c->r);
440
441
442  for (int n=0;((n<c->n) && (i_con[n]>=0));n++){
443    if (i_con[n]==j){
444      now_t_rep(i,j,c);
445      omfree(i_con);
446
447      return TRUE;
448    }
449  }
450  omfree(i_con);
451
452  return FALSE;
453}
454BOOLEAN lenS_correct(kStrategy strat){
455  int i;
456  for(i=0;i<=strat->sl;i++){
457    if (strat->lenS[i]!=pLength(strat->S[i]))
458      return FALSE;
459  }
460  return TRUE;
461}
462
463static void notice_miss(int i, int j, calc_dat* c){
464  if (TEST_OPT_PROT)
465    PrintS("-");
466 
467}
468
469static void cleanS(kStrategy strat, calc_dat* c){
470  int i=0;
471  LObject P;
472  while(i<=strat->sl){
473    P.p=strat->S[i];
474    P.sev=strat->sevS[i];
475    if(kFindDivisibleByInS(strat->S,strat->sevS,strat->sl,&P)!=i)
476    {
477      deleteInS(i,strat);
478      //remember destroying poly
479      BOOLEAN found=FALSE;
480      int j;
481      for(j=0;j<c->n;j++)
482        if(c->S->m[j]==P.p)
483        {
484          found=TRUE;
485          break;
486        }
487      if (!found)
488        pDelete(&P.p);
489      //remember additional reductors
490    }
491    else i++;
492  }
493}
494static int bucket_guess(kBucket* bucket){
495  int sum=0;
496  int i;
497  for (i=MAX_BUCKET;i>=0;i--){
498    sum+=bucket->buckets_length[i];
499  }
500  return sum;
501}
502
503
504
505
506
507
508static int add_to_reductors(calc_dat* c, poly h, int len){
509  //inDebug(h);
510  assume(lenS_correct(c->strat));
511 
512  int i;
513  if (c->is_char0)
514       i=simple_posInS(c->strat,h,pSLength(h,len),c->is_char0);
515  else
516    i=simple_posInS(c->strat,h,len,c->is_char0);
517 
518  LObject P; memset(&P,0,sizeof(P));
519  P.tailRing=c->r;
520  P.p=h; /*p_Copy(h,c->r);*/
521  P.FDeg=pFDeg(P.p,c->r);
522 
523  if (!rField_is_Zp(c->r)){ 
524    pCleardenom(P.p);
525    pContent(P.p); //is a duplicate call, but belongs here
526   
527  }
528  else                     
529    pNorm(P.p);
530  pNormalize(P.p);
531
532  c->strat->enterS(P,i,c->strat);
533 
534 
535
536  c->strat->lenS[i]=len;
537 
538  if(c->strat->lenSw)
539    c->strat->lenSw[i]=pSLength(P.p,len);
540  return i;
541 
542}
543static void length_one_crit(calc_dat* c, int pos, int len)
544{
545  if (len==1)
546  {
547    int i;
548    for ( i=0;i<pos;i++)
549    {
550      if (c->lengths[i]==1)
551        c->states[pos][i]=HASTREP;
552    }
553    for ( i=pos+1;i<c->n;i++){
554      if (c->lengths[i]==1)
555        c->states[i][pos]=HASTREP;
556    }
557    shorten_tails(c,c->S->m[pos]);
558  }
559}
560static sorted_pair_node* find_next_pair2(calc_dat* c, BOOLEAN go_higher){
561  clean_top_of_pair_list(c);
562  sorted_pair_node* s=pop_pair(c);
563
564
565  return s;
566}
567
568static void move_forward_in_S(int old_pos, int new_pos,kStrategy strat, BOOLEAN is_char0)
569{
570  assume(old_pos>=new_pos);
571  poly p=strat->S[old_pos];
572  int ecart=strat->ecartS[old_pos];
573  long sev=strat->sevS[old_pos];
574  int s_2_r=strat->S_2_R[old_pos];
575  int length=strat->lenS[old_pos];
576  int length_w;
577  if(is_char0)
578    length_w=strat->lenSw[old_pos];
579  int i;
580  for (i=old_pos; i>new_pos; i--)
581  {
582    strat->S[i] = strat->S[i-1];
583    strat->ecartS[i] = strat->ecartS[i-1];
584    strat->sevS[i] = strat->sevS[i-1];
585    strat->S_2_R[i] = strat->S_2_R[i-1];
586  }
587  if (strat->lenS!=NULL)
588    for (i=old_pos; i>new_pos; i--)
589      strat->lenS[i] = strat->lenS[i-1];
590  if (strat->lenSw!=NULL)
591    for (i=old_pos; i>new_pos; i--)
592      strat->lenSw[i] = strat->lenSw[i-1];
593
594  strat->S[new_pos]=p;
595  strat->ecartS[new_pos]=ecart;
596  strat->sevS[new_pos]=sev;
597  strat->S_2_R[new_pos]=s_2_r;
598  strat->lenS[new_pos]=length;
599  if(is_char0)
600    strat->lenSw[new_pos]=length_w;
601  //assume(lenS_correct(strat));
602}
603static void replace_pair(int & i, int & j, calc_dat* c)
604{
605  c->soon_free=NULL;
606  int curr_deg;
607  poly lm=pOne();
608
609  pLcm(c->S->m[i], c->S->m[j], lm);
610  pSetm(lm);
611  int deciding_deg= pTotaldegree(lm);
612  int* i_con =make_connections(i,j,lm,c);
613  int z=0;
614
615  for (int n=0;((n<c->n) && (i_con[n]>=0));n++){
616    if (i_con[n]==j){
617      now_t_rep(i,j,c);
618      omfree(i_con);
619      p_Delete(&lm,c->r);
620      return;
621    }
622  }
623
624  int* j_con =make_connections(j,lm,c);
625  i= i_con[0];
626  j=j_con[0];
627  if(c->n>1){
628    if (i_con[1]>=0)
629      i=i_con[1];
630    else {
631      if (j_con[1]>=0)
632        j=j_con[1];
633    }
634  }
635  pLcm(c->S->m[i], c->S->m[j], lm);
636  pSetm(lm);
637  poly short_s;
638  curr_deg=pTotaldegree(lm);
639  int_pair_node* last=NULL;
640
641  for (int n=0;((n<c->n) && (j_con[n]>=0));n++){
642    for (int m=0;((m<c->n) && (i_con[m]>=0));m++){
643      pLcm(c->S->m[i_con[m]], c->S->m[j_con[n]], lm);
644      pSetm(lm);
645      if (pTotaldegree(lm)>=deciding_deg)
646      {
647        soon_t_rep(i_con[m],j_con[n],c);
648        int_pair_node* h= (int_pair_node*)omalloc(sizeof(int_pair_node));
649        if (last!=NULL)
650          last->next=h;
651        else
652          c->soon_free=h;
653        h->next=NULL;
654        h->a=i_con[m];
655        h->b=j_con[n];
656        last=h;
657      }
658      //      if ((comp_deg<curr_deg)
659      //  ||
660      //  ((comp_deg==curr_deg) &&
661      short_s=ksCreateShortSpoly(c->S->m[i_con[m]],c->S->m[j_con[n]],c->r);
662      if (short_s==NULL) {
663        i=i_con[m];
664        j=j_con[n];
665        now_t_rep(i_con[m],j_con[n],c);
666        p_Delete(&lm,c->r);
667        omfree(i_con);
668        omfree(j_con);
669
670        return;
671      }
672#ifdef QUICK_SPOLY_TEST
673      for (int dz=0;dz<=c->n;dz++){
674        if (dz==c->n) {
675          //have found not head reducing pair
676          i=i_con[m];
677          j=j_con[n];
678          p_Delete(&short_s,c->r);
679          p_Delete(&lm,c->r);
680          omfree(i_con);
681          omfree(j_con);
682
683          return;
684        }
685        if (p_LmDivisibleBy(c->S->m[dz],short_s,c->r)) break;
686      }
687#endif
688      int comp_deg(pTotaldegree(short_s));
689      p_Delete(&short_s,c->r);
690      if ((comp_deg<curr_deg))
691         
692      {
693        curr_deg=comp_deg;
694        i=i_con[m];
695        j=j_con[n];
696      }
697    }
698  }
699  p_Delete(&lm,c->r);
700  omfree(i_con);
701  omfree(j_con);
702  return;
703}
704
705
706static int* make_connections(int from, poly bound, calc_dat* c)
707{
708  ideal I=c->S;
709  int s=pTotaldegree(bound);
710  int* cans=(int*) omalloc(c->n*sizeof(int));
711  int* connected=(int*) omalloc(c->n*sizeof(int));
712  int cans_length=0;
713  connected[0]=from;
714  int connected_length=1;
715  long neg_bounds_short= ~p_GetShortExpVector(bound,c->r);
716  for (int i=0;i<c->n;i++){
717    if (c->T_deg[i]>s) continue;
718    if (i!=from){
719      if(p_LmShortDivisibleBy(I->m[i],c->short_Exps[i],bound,neg_bounds_short,c->r)){
720        cans[cans_length]=i;
721        cans_length++;
722      }
723    }
724  }
725  int not_yet_found=cans_length;
726  int con_checked=0;
727  int pos;
728  while((not_yet_found>0) && (con_checked<connected_length)){
729    pos=connected[con_checked];
730    for(int i=0;i<cans_length;i++){
731      if (cans[i]<0) continue;
732      if (has_t_rep(pos,cans[i],c))
733      {
734        connected[connected_length]=cans[i];
735        connected_length++;
736        cans[i]=-1;
737        --not_yet_found;
738      }
739    }
740    con_checked++;
741  }
742  if (connected_length<c->n){
743    connected[connected_length]=-1;
744  }
745  omfree(cans);
746  return connected;
747}
748static int* make_connections(int from, int to, poly bound, calc_dat* c)
749{
750  ideal I=c->S;
751  int s=pTotaldegree(bound);
752  int* cans=(int*) omalloc(c->n*sizeof(int));
753  int* connected=(int*) omalloc(c->n*sizeof(int));
754  cans[0]=to;
755  int cans_length=1;
756  connected[0]=from;
757  int last_cans_pos=-1;
758  int connected_length=1;
759  long neg_bounds_short= ~p_GetShortExpVector(bound,c->r);
760
761  int not_yet_found=cans_length;
762  int con_checked=0;
763  int pos;
764  BOOLEAN can_find_more=TRUE;
765  while(TRUE){
766    if ((con_checked<connected_length)&& (not_yet_found>0)){
767      pos=connected[con_checked];
768      for(int i=0;i<cans_length;i++){
769        if (cans[i]<0) continue;
770        if (has_t_rep(pos,cans[i],c))//||(trivial_syzygie(pos,cans[i],bound,c))
771{
772
773          connected[connected_length]=cans[i];
774          connected_length++;
775          cans[i]=-1;
776          --not_yet_found;
777
778          if (connected[connected_length-1]==to){
779            if (connected_length<c->n){
780              connected[connected_length]=-1;
781            }
782            omfree(cans);
783            return connected;
784          }
785        }
786      }
787      con_checked++;
788    }
789    else
790    {
791      for(last_cans_pos++;last_cans_pos<=c->n;last_cans_pos++){
792        if (last_cans_pos==c->n){
793          if (connected_length<c->n){
794            connected[connected_length]=-1;
795          }
796          omfree(cans);
797          return connected;
798        }
799        if ((last_cans_pos==from)||(last_cans_pos==to))
800          continue;
801        if(p_LmShortDivisibleBy(I->m[last_cans_pos],c->short_Exps[last_cans_pos],bound,neg_bounds_short,c->r)){
802          cans[cans_length]=last_cans_pos;
803          cans_length++;
804          break;
805        }
806      }
807      not_yet_found++;
808      for (int i=0;i<con_checked;i++){
809        if (has_t_rep(connected[i],last_cans_pos,c)){
810
811          connected[connected_length]=last_cans_pos;
812          connected_length++;
813          cans[cans_length-1]=-1;
814
815          --not_yet_found;
816          if (connected[connected_length-1]==to){
817            if (connected_length<c->n){
818              connected[connected_length]=-1;
819            }
820
821            omfree(cans);
822            return connected;
823          }
824          break;
825        }
826      }
827    }
828  }
829  if (connected_length<c->n){
830    connected[connected_length]=-1;
831  }
832
833  omfree(cans);
834  return connected;
835}
836#ifdef HEAD_BIN
837static inline poly p_MoveHead(poly p, omBin b)
838{
839  poly np;
840  omTypeAllocBin(poly, np, b);
841  memmove(np, p, b->sizeW*sizeof(long));
842  omFreeBinAddr(p);
843  return np;
844}
845#endif
846
847
848
849//len should be weighted length in char 0
850static int simple_posInS (kStrategy strat, poly p,int len, BOOLEAN is_char0)
851{
852
853
854  if(strat->sl==-1) return 0;
855  polyset set=strat->S;
856  intset setL=strat->lenS;
857  if (is_char0) setL=strat->lenSw;
858  int length=strat->sl;
859  int i;
860  int an = 0;
861  int en= length;
862
863  if ((len>setL[length])
864      || ((len==setL[length]) && (pLmCmp(set[length],p)== -1)))
865    return length+1;
866
867  loop
868  {
869    if (an >= en-1)
870    {
871      if ((len<setL[an])
872          || ((len==setL[an]) && (pLmCmp(set[an],p) == 1))) return an;
873      return en;
874    }
875    i=(an+en) / 2;
876    if ((len<setL[i])
877        || ((len==setL[i]) && (pLmCmp(set[i],p) == 1))) en=i;
878    //else if ((len>setL[i])
879    //|| ((len==setL[i]) && (pLmCmp(set[i],p) == -1))) an=i;
880    else an=i;
881  }
882}
883/*2
884 *if the leading term of p
885 *divides the leading term of some S[i] it will be canceled
886 */
887static inline void clearS (poly p, unsigned long p_sev,int l, int* at, int* k,
888                           kStrategy strat)
889{
890  assume(p_sev == pGetShortExpVector(p));
891  if (!pLmShortDivisibleBy(p,p_sev, strat->S[*at], ~ strat->sevS[*at])) return;
892  if (l>=strat->lenS[*at]) return;
893  if (TEST_OPT_PROT)
894    PrintS("!");
895  mflush();
896  //pDelete(&strat->S[*at]);
897  deleteInS((*at),strat);
898  (*at)--;
899  (*k)--;
900//  assume(lenS_correct(strat));
901}
902static sorted_pair_node** add_to_basis(poly h, int i_pos, int j_pos,calc_dat* c, int* ip)
903{
904
905  assume(h!=NULL);
906//  BOOLEAN corr=lenS_correct(c->strat);
907  BOOLEAN R_found=FALSE;
908  void* hp;
909
910  ++(c->n);
911  ++(c->S->ncols);
912  int i,j;
913  i=c->n-1;
914  sorted_pair_node** nodes=(sorted_pair_node**) omalloc(sizeof(sorted_pair_node*)*i);
915  int spc=0;
916  c->T_deg=(int*) omrealloc(c->T_deg,c->n*sizeof(int));
917  c->T_deg[i]=pTotaldegree(h);
918  c->tmp_pair_lm=(poly*) omrealloc(c->tmp_pair_lm,c->n*sizeof(poly));
919  c->tmp_pair_lm[i]=pOne_Special(c->r);
920  hp=omrealloc(c->rep, c->n *sizeof(int));
921  if (hp!=NULL){
922    c->rep=(int*) hp;
923  } else {
924    exit(1);
925  }
926  c->short_Exps=(long *) omrealloc(c->short_Exps ,c->n*sizeof(long));
927
928  hp=omrealloc(c->lengths, c->n *sizeof(int));
929  if (hp!=NULL){
930    c->lengths=(int*) hp;
931  } else {
932    exit(1);
933  }
934  c->lengths[i]=pLength(h);
935  hp=omrealloc(c->states, c->n * sizeof(char*));
936 
937    c->states=(char**) hp;
938  c->gcd_of_terms=(poly*) omrealloc(c->gcd_of_terms, c->n *sizeof(poly));
939  c->gcd_of_terms[i]=gcd_of_terms(h,c->r);
940  c->rep[i]=i;
941  hp=omalloc(i*sizeof(char));
942  if (hp!=NULL){
943    c->states[i]=(char*) hp;
944  } else {
945    exit(1);
946  }
947  hp=omrealloc(c->S->m,c->n*sizeof(poly));
948  if (hp!=NULL){
949    c->S->m=(poly*) hp;
950  } else {
951    exit(1);
952  }
953  c->S->m[i]=h;
954  c->short_Exps[i]=p_GetShortExpVector(h,c->r);
955  for (j=0;j<i;j++){
956    if (c->rep[j]==j){
957      //check product criterion
958
959      c->states[i][j]=UNCALCULATED;
960      assume(p_LmDivisibleBy(c->S->m[i],c->S->m[j],c->r)==
961             p_LmShortDivisibleBy(c->S->m[i],c->short_Exps[i],c->S->m[j],~(c->short_Exps[j]),c->r));
962      if(!c->F4_mode)
963      {
964        assume(!(p_LmDivisibleBy(c->S->m[j],c->S->m[i],c->r)));
965      }
966      //lies I[i] under I[j] ?
967      if(p_LmShortDivisibleBy(c->S->m[i],c->short_Exps[i],c->S->m[j],~(c->short_Exps[j]),c->r)){
968        c->rep[j]=i;
969        if (TEST_OPT_PROT)
970          PrintS("R"); 
971        R_found=TRUE;
972
973        c->Rcounter++;
974        if((i_pos>=0) && (j_pos>=0)){
975       
976        }
977        for(int z=0;z<j;z++){
978          if(c->rep[z]!=z) continue;
979          if (c->states[j][z]==UNCALCULATED){
980            c->states[j][z]=UNIMPORTANT;
981          }
982        }
983        for(int z=j+1;z<i;z++){
984          if(c->rep[z]!=z) continue;
985          if (c->states[z][j]==UNCALCULATED){
986            c->states[z][j]=UNIMPORTANT;
987          }
988        }
989      }
990    }
991    else {
992      c->states[i][j]=UNIMPORTANT;
993    }
994    if ((c->lengths[i]==1) && (c->lengths[j]==1))
995      c->states[i][j]=HASTREP;
996    else if (pHasNotCF(c->S->m[i],c->S->m[j])){
997      c->easy_product_crit++;
998      c->states[i][j]=HASTREP;
999    }
1000                        else if(extended_product_criterion(c->S->m[i],c->gcd_of_terms[i],c->S->m[j],c->gcd_of_terms[j],c)){
1001                                        c->states[i][j]=HASTREP;
1002                                        c->extended_product_crit++;
1003                                        //PrintS("E");
1004                        }
1005    if (c->states[i][j]==UNCALCULATED){
1006
1007     
1008//      poly short_s=ksCreateShortSpoly(c->S->m[i],c->S->m[j],c->r);
1009      //    if (short_s)
1010      //    {
1011        sorted_pair_node* s=(sorted_pair_node*) omalloc(sizeof(sorted_pair_node));
1012        s->i=max(i,j);
1013        s->j=min(i,j);
1014        s->expected_length=c->lengths[i]+c->lengths[j]-2;
1015     
1016        poly lm=pOne();
1017
1018        pLcm(c->S->m[i], c->S->m[j], lm);
1019        pSetm(lm);
1020        s->deg=pTotaldegree(lm);
1021        s->lcm_of_lm=lm;
1022//          pDelete(&short_s);
1023        //assume(lm!=NULL);
1024        nodes[spc]=s;
1025        spc++;
1026        // }
1027        //else
1028        //{
1029        //c->states[i][j]=HASTREP;
1030        //}
1031    }
1032  }
1033
1034  add_to_reductors(c, h, c->lengths[c->n-1]);
1035  //i=posInS(c->strat,c->strat->sl,h,0 ecart);
1036
1037  if (c->lengths[c->n-1]==1)
1038    shorten_tails(c,c->S->m[c->n-1]);
1039  //you should really update c->lengths, c->strat->lenS, and the oder of polys in strat if you sort after lengths
1040
1041  //for(i=c->strat->sl; i>0;i--)
1042  //  if(c->strat->lenS[i]<c->strat->lenS[i-1]) printf("fehler bei %d\n",i);
1043  if (c->Rcounter>50) {
1044    c->Rcounter=0;
1045    cleanS(c->strat,c);
1046  }
1047  if(!ip){
1048    qsort(nodes,spc,sizeof(sorted_pair_node*),pair_better_gen2);
1049 
1050   
1051    c->apairs=merge(c->apairs,c->pair_top+1,nodes,spc,c);
1052    c->pair_top+=spc;
1053    clean_top_of_pair_list(c);
1054    omfree(nodes);
1055    return NULL;
1056  }
1057  {
1058    *ip=spc;
1059    return nodes;
1060  }
1061
1062 
1063
1064}
1065
1066
1067static int iq_crit(const void* ap,const void* bp){
1068
1069  sorted_pair_node* a=*((sorted_pair_node**)ap);
1070  sorted_pair_node* b=*((sorted_pair_node**)bp);
1071  assume(a->i>a->j);
1072  assume(b->i>b->j);
1073  int comp=pLmCmp(a->lcm_of_lm, b->lcm_of_lm);
1074  if(comp!=0)
1075    return comp;
1076  if (a->deg<b->deg) return -1;
1077  if (a->deg>b->deg) return 1;
1078
1079
1080  if (a->expected_length<b->expected_length) return -1;
1081  if (a->expected_length>b->expected_length) return 1;
1082  if (a->j>b->j) return 1;
1083  if (a->j<b->j) return -1;
1084  return 0;
1085}
1086
1087static sorted_pair_node** add_to_basis_ideal_quotient(poly h, int i_pos, int j_pos,calc_dat* c, int* ip)
1088{
1089
1090  assume(h!=NULL);
1091//  BOOLEAN corr=lenS_correct(c->strat);
1092  BOOLEAN R_found=FALSE;
1093  void* hp;
1094
1095  ++(c->n);
1096  ++(c->S->ncols);
1097  int i,j;
1098  i=c->n-1;
1099  sorted_pair_node** nodes=(sorted_pair_node**) omalloc(sizeof(sorted_pair_node*)*i);
1100  int spc=0;
1101  c->T_deg=(int*) omrealloc(c->T_deg,c->n*sizeof(int));
1102  c->T_deg[i]=pTotaldegree(h);
1103  c->tmp_pair_lm=(poly*) omrealloc(c->tmp_pair_lm,c->n*sizeof(poly));
1104  c->tmp_pair_lm[i]=pOne_Special(c->r);
1105  hp=omrealloc(c->rep, c->n *sizeof(int));
1106  if (hp!=NULL){
1107    c->rep=(int*) hp;
1108  } else {
1109    exit(1);
1110  }
1111  c->short_Exps=(long *) omrealloc(c->short_Exps ,c->n*sizeof(long));
1112
1113  hp=omrealloc(c->lengths, c->n *sizeof(int));
1114  if (hp!=NULL){
1115    c->lengths=(int*) hp;
1116  } else {
1117    exit(1);
1118  }
1119  c->lengths[i]=pLength(h);
1120  hp=omrealloc(c->states, c->n * sizeof(char*));
1121 
1122    c->states=(char**) hp;
1123  c->gcd_of_terms=(poly*) omrealloc(c->gcd_of_terms, c->n *sizeof(poly));
1124  c->gcd_of_terms[i]=gcd_of_terms(h,c->r);
1125  c->rep[i]=i;
1126  hp=omalloc(i*sizeof(char));
1127  if (hp!=NULL){
1128    c->states[i]=(char*) hp;
1129  } else {
1130    exit(1);
1131  }
1132  hp=omrealloc(c->S->m,c->n*sizeof(poly));
1133  if (hp!=NULL){
1134    c->S->m=(poly*) hp;
1135  } else {
1136    exit(1);
1137  }
1138  c->S->m[i]=h;
1139  c->short_Exps[i]=p_GetShortExpVector(h,c->r);
1140  for (j=0;j<i;j++){
1141   
1142    //check product criterion
1143   
1144    c->states[i][j]=UNCALCULATED;
1145    assume(p_LmDivisibleBy(c->S->m[i],c->S->m[j],c->r)==
1146           p_LmShortDivisibleBy(c->S->m[i],c->short_Exps[i],c->S->m[j],~(c->short_Exps[j]),c->r));
1147    if(!c->F4_mode)
1148    {
1149      assume(!(p_LmDivisibleBy(c->S->m[j],c->S->m[i],c->r)));
1150    }
1151    //lies I[i] under I[j] ?
1152   
1153    if ((c->lengths[i]==1) && (c->lengths[j]==1))
1154      c->states[i][j]=HASTREP;
1155    else if (pHasNotCF(c->S->m[i],c->S->m[j]))
1156    {
1157      c->easy_product_crit++;
1158      c->states[i][j]=HASTREP;
1159    }
1160    else if(extended_product_criterion(c->S->m[i],c->gcd_of_terms[i],c->S->m[j],c->gcd_of_terms[j],c))
1161    {
1162      c->states[i][j]=HASTREP;
1163      c->extended_product_crit++;
1164      //PrintS("E");
1165    }
1166      //  if (c->states[i][j]==UNCALCULATED){
1167
1168     
1169//      poly short_s=ksCreateShortSpoly(c->S->m[i],c->S->m[j],c->r);
1170      //    if (short_s)
1171      //    {
1172    sorted_pair_node* s=(sorted_pair_node*) omalloc(sizeof(sorted_pair_node));
1173    s->i=max(i,j);
1174    s->j=min(i,j);
1175    s->expected_length=c->lengths[i]+c->lengths[j]-2;
1176     
1177    poly lm=c->tmp_pair_lm[j];//=pOne_Special();
1178     
1179    pLcm(c->S->m[i], c->S->m[j], lm);
1180    pSetm(lm);
1181    s->deg=pTotaldegree(lm);
1182    s->lcm_of_lm=lm;
1183    //          pDelete(&short_s);
1184    //assume(lm!=NULL);
1185    nodes[spc]=s;
1186    spc++;
1187        // }
1188        //else
1189        //{
1190        //c->states[i][j]=HASTREP;
1191        //}
1192  }
1193 
1194  assume(spc==i);
1195  //now ideal quotient crit
1196  qsort(nodes,spc,sizeof(sorted_pair_node*),iq_crit);
1197 
1198    sorted_pair_node** nodes_final=(sorted_pair_node**) omalloc(sizeof(sorted_pair_node*)*i);
1199  int spc_final=0;
1200  j=0;
1201  while(j<spc)
1202  {
1203    int lower=j;
1204    int upper;
1205    BOOLEAN has=FALSE;
1206    for(upper=lower+1;upper<spc;upper++)
1207    {
1208     
1209      if(!pLmEqual(nodes[lower]->lcm_of_lm,nodes[upper]->lcm_of_lm))
1210      {
1211        break;
1212      }
1213      if (has_t_rep(nodes[upper]->i,nodes[upper]->j,c))
1214        has=TRUE;
1215
1216    }
1217    upper=upper-1;
1218    int z;
1219    assume(spc_final<=j);
1220    for(z=0;z<spc_final;z++)
1221    {
1222      if(p_LmDivisibleBy(nodes_final[z]->lcm_of_lm,nodes[lower]->lcm_of_lm,c->r))
1223      {
1224        has=TRUE;
1225        break;
1226      }
1227    }
1228   
1229    if(has)
1230    {
1231      for(;lower<=upper;lower++)
1232      {
1233        //free_sorted_pair_node(nodes[lower],c->r);
1234        omfree(nodes[lower]);
1235        nodes[lower]=NULL;
1236      }
1237      j=upper+1;
1238      continue;
1239    }
1240    else
1241    {
1242      nodes[lower]->lcm_of_lm=pCopy(nodes[lower]->lcm_of_lm);
1243      nodes_final[spc_final++]=nodes[lower];
1244     
1245      nodes[lower]=NULL;
1246      for(lower=lower+1;lower<=upper;lower++)
1247      {
1248        //      free_sorted_pair_node(nodes[lower],c->r);
1249        omfree(nodes[lower]);
1250        nodes[lower]=NULL;
1251      }
1252      j=upper+1;
1253      continue;
1254    }
1255  }
1256
1257  //  Print("i:%d,spc_final:%d",i,spc_final);
1258
1259
1260
1261
1262  assume(spc_final<=spc);
1263  omfree(nodes);
1264  nodes=NULL;
1265
1266  add_to_reductors(c, h, c->lengths[c->n-1]);
1267  //i=posInS(c->strat,c->strat->sl,h,0 ecart);
1268
1269  if (c->lengths[c->n-1]==1)
1270    shorten_tails(c,c->S->m[c->n-1]);
1271  //you should really update c->lengths, c->strat->lenS, and the oder of polys in strat if you sort after lengths
1272
1273  //for(i=c->strat->sl; i>0;i--)
1274  //  if(c->strat->lenS[i]<c->strat->lenS[i-1]) printf("fehler bei %d\n",i);
1275  if (c->Rcounter>50) {
1276    c->Rcounter=0;
1277    cleanS(c->strat,c);
1278  }
1279  if(!ip){
1280    qsort(nodes_final,spc_final,sizeof(sorted_pair_node*),pair_better_gen2);
1281 
1282   
1283    c->apairs=merge(c->apairs,c->pair_top+1,nodes_final,spc_final,c);
1284    c->pair_top+=spc_final;
1285    clean_top_of_pair_list(c);
1286    omfree(nodes_final);
1287    return NULL;
1288  }
1289  {
1290    *ip=spc_final;
1291    return nodes_final;
1292  }
1293
1294 
1295
1296}
1297
1298
1299
1300
1301
1302
1303#if 0
1304static poly redNF (poly h,kStrategy strat)
1305{
1306  int j = 0;
1307  int z = 3;
1308  unsigned long not_sev;
1309
1310  if (0 > strat->sl)
1311  {
1312    return h;
1313  }
1314  not_sev = ~ pGetShortExpVector(h);
1315  loop
1316    {
1317      if (pLmShortDivisibleBy(strat->S[j], strat->sevS[j], h, not_sev))
1318      {
1319        //if (strat->interpt) test_int_std(strat->kIdeal);
1320        /*- compute the s-polynomial -*/
1321#ifdef KDEBUG
1322        if (TEST_OPT_DEBUG)
1323        {
1324         
1325          PrintS("red:");
1326          wrp(h);
1327          PrintS(" with ");
1328          wrp(strat->S[j]);
1329        }
1330#endif
1331        h = ksOldSpolyRed(strat->S[j],h,strat->kNoether);
1332#ifdef KDEBUG
1333        if (TEST_OPT_DEBUG)
1334        {
1335          PrintS("\nto:");
1336          wrp(h);
1337          PrintLn();
1338        }
1339#endif
1340        if (h == NULL) return NULL;
1341        z++;
1342        if (z>=10)
1343        {
1344          z=0;
1345          pNormalize(h);
1346        }
1347        /*- try to reduce the s-polynomial -*/
1348        j = 0;
1349        not_sev = ~ pGetShortExpVector(h);
1350      }
1351      else
1352      {
1353        if (j >= strat->sl) return h;
1354        j++;
1355      }
1356    }
1357}
1358#else
1359
1360static poly redNF2 (poly h,calc_dat* c , int &len, number&  m,int n)
1361{
1362  m=nInit(1);
1363  if (h==NULL) return NULL;
1364
1365  assume(len==pLength(h));
1366  kStrategy strat=c->strat;
1367  if (0 > strat->sl)
1368  {
1369    return h;
1370  }
1371  int j;
1372 
1373  LObject P(h);
1374  P.SetShortExpVector();
1375  P.bucket = kBucketCreate(currRing);
1376  // BOOLEAN corr=lenS_correct(strat);
1377  kBucketInit(P.bucket,P.p,len /*pLength(P.p)*/);
1378  //int max_pos=simple_posInS(strat,P.p);
1379  loop
1380    {
1381
1382      j=kFindDivisibleByInS(strat->S,strat->sevS,strat->sl,&P);
1383      if ((j>=0) && ((!n)||(strat->lenS[j]<=n)))
1384      {
1385
1386       
1387        nNormalize(pGetCoeff(P.p));
1388#ifdef KDEBUG
1389        if (TEST_OPT_DEBUG)
1390        {
1391          PrintS("red:");
1392          wrp(h);
1393          PrintS(" with ");
1394          wrp(strat->S[j]);
1395        }
1396#endif
1397       
1398        number coef=kBucketPolyRed(P.bucket,strat->S[j],
1399                                   strat->lenS[j]/*pLength(strat->S[j])*/,
1400                                   strat->kNoether);
1401        number m2=nMult(m,coef);
1402        nDelete(&m);
1403        m=m2;
1404        nDelete(&coef);
1405        h = kBucketGetLm(P.bucket);
1406       
1407        if (h==NULL) {
1408          len=0;
1409          kBucketDestroy(&P.bucket);
1410          return 
1411          NULL;}
1412        P.p=h;
1413        P.t_p=NULL;
1414        P.SetShortExpVector();
1415#ifdef KDEBUG
1416        if (TEST_OPT_DEBUG)
1417        {
1418          PrintS("\nto:");
1419          wrp(h);
1420          PrintLn();
1421        }
1422#endif
1423      }
1424      else
1425      {
1426        kBucketClear(P.bucket,&(P.p),&len);
1427        kBucketDestroy(&P.bucket);
1428        pNormalize(P.p);
1429        assume(len==(pLength(P.p)));
1430        return P.p;
1431      }
1432    }
1433}
1434
1435
1436static poly redTailShort(poly h, kStrategy strat){
1437
1438  int sl=strat->sl;
1439  int i;
1440  int len=pLength(h);
1441  for(i=0;i<=strat->sl;i++){
1442    if(strat->lenS[i]>2)
1443      break;
1444  }
1445  return(redNFTail(h,i-1,strat, len));
1446}
1447
1448static void line_of_extended_prod(int fixpos,calc_dat* c){
1449    if (c->gcd_of_terms[fixpos]==NULL)
1450  {
1451    c->gcd_of_terms[fixpos]=gcd_of_terms(c->S->m[fixpos],c->r);
1452    if (c->gcd_of_terms[fixpos])
1453    {
1454      int i;
1455      for(i=0;i<fixpos;i++)
1456        if((c->states[fixpos][i]!=HASTREP)&& (extended_product_criterion(c->S->m[fixpos],c->gcd_of_terms[fixpos], c->S->m[i],c->gcd_of_terms[i],c)))
1457{
1458          c->states[fixpos][i]=HASTREP;
1459          c->extended_product_crit++;
1460}     
1461      for(i=fixpos+1;i<c->n;i++)
1462        if((c->states[i][fixpos]!=HASTREP)&& (extended_product_criterion(c->S->m[fixpos],c->gcd_of_terms[fixpos], c->S->m[i],c->gcd_of_terms[i],c)))
1463        {        c->states[i][fixpos]=HASTREP;
1464        c->extended_product_crit++;
1465        }
1466    }
1467  }
1468}
1469static void c_S_element_changed_hook(int pos, calc_dat* c){
1470  length_one_crit(c,pos, c->lengths[pos]);
1471  line_of_extended_prod(pos,c);
1472}
1473class poly_tree_node {
1474public:
1475  poly p;
1476  poly_tree_node* l;
1477  poly_tree_node* r;
1478  int n;
1479  poly_tree_node(int sn):l(NULL),r(NULL),n(sn){}
1480};
1481class exp_number_builder{
1482public:
1483  poly_tree_node* top_level;
1484  int n;
1485  int get_n(poly p);
1486  exp_number_builder():top_level(0),n(0){}
1487};
1488int exp_number_builder::get_n(poly p){
1489  poly_tree_node** node=&top_level;
1490  while(*node!=NULL){
1491    int c=pLmCmp(p,(*node)->p);
1492    if (c==0) return (*node)->n;
1493    if (c==-1) node=&((*node)->r);
1494    else
1495      node=&((*node)->l);
1496  }
1497  (*node)= new poly_tree_node(n);
1498  n++;
1499  (*node)->p=pLmInit(p);
1500  return (*node)->n;
1501}
1502
1503//mac_polys exp are smaller iff they are greater by monomial ordering
1504//corresponding to solving linear equations notation
1505struct int_poly_pair{
1506  poly p;
1507  int n;
1508};
1509
1510void t2ippa_rec(poly* ip,int* ia, poly_tree_node* k, int &offset){
1511    if(!k) return;
1512    t2ippa_rec(ip,ia,k->l,offset);
1513    ip[offset]=k->p;
1514    ia[k->n]=offset;
1515    ++offset;
1516
1517    t2ippa_rec(ip,ia,k->r,offset);
1518    delete k;
1519  }
1520void t2ippa(poly* ip,int* ia,exp_number_builder & e){
1521
1522  int o=0;
1523  t2ippa_rec(ip,ia,e.top_level,o);
1524}
1525int anti_poly_order(const void* a, const void* b){
1526  return -pLmCmp(((int_poly_pair*) a)->p,((int_poly_pair*) b)->p );
1527}
1528mac_poly mac_p_add_ff_qq(mac_poly a, number f,mac_poly b){
1529  mac_poly erg;
1530  mac_poly* set_this;
1531  set_this=&erg;
1532  while((a!=NULL) &&(b!=NULL)){
1533    if (a->exp<b->exp){
1534      (*set_this)=a;
1535      a=a->next;
1536      set_this= &((*set_this)->next);
1537    } 
1538    else{
1539      if (a->exp>b->exp){
1540        mac_poly in =new mac_poly_r();
1541        in->exp=b->exp;
1542        in->coef=nMult(b->coef,f);
1543        (*set_this)=in;
1544        b=b->next;
1545        set_this= &((*set_this)->next);
1546      }
1547      else {
1548        //a->exp==b->ecp
1549        number n=nMult(b->coef,f);
1550        number n2=nAdd(a->coef,n);
1551        nDelete(&n);
1552        nDelete(&(a->coef));
1553        if (nIsZero(n2)){
1554          nDelete(&n2);
1555          mac_poly ao=a;
1556          a=a->next;
1557          delete ao;
1558          b=b->next;
1559         
1560        } else {
1561          a->coef=n2;
1562          b=b->next;
1563          (*set_this)=a;
1564          a=a->next;
1565          set_this= &((*set_this)->next);
1566        }
1567 
1568      }
1569   
1570    }
1571  }
1572  if((a==NULL)&&(b==NULL)){
1573    (*set_this)=NULL;
1574    return erg;
1575  }
1576  if (b==NULL) {
1577    (*set_this=a);
1578    return erg;
1579  }
1580 
1581  //a==NULL
1582  while(b!=NULL){
1583    mac_poly mp= new mac_poly_r();
1584    mp->exp=b->exp;
1585    mp->coef=nMult(f,b->coef);
1586    (*set_this)=mp;
1587    set_this=&(mp->next);
1588    b=b->next;
1589  }
1590  (*set_this)=NULL;
1591  return erg;
1592 
1593}
1594void mac_mult_cons(mac_poly p,number c){
1595  while(p){
1596    number m=nMult(p->coef,c);
1597    nDelete(&(p->coef));
1598    p->coef=m;
1599    p=p->next;
1600  }
1601 
1602}
1603int mac_length(mac_poly p){
1604  int l=0;
1605  while(p){
1606    l++;
1607    p=p->next;
1608  }
1609  return l;
1610}
1611//contrary to delete on the mac_poly_r, the coefficients are also destroyed here
1612void mac_destroy(mac_poly p){
1613  mac_poly iter=p;
1614  while(iter)
1615  {
1616    mac_poly next=iter->next;
1617    nDelete(&iter->coef);
1618    delete iter;
1619    iter=next;
1620  }
1621}
1622BOOLEAN is_valid_ro(red_object & ro){
1623  red_object r2=ro;
1624  ro.validate();
1625  if ((r2.p!=ro.p)||(r2.sev!=ro.sev)||(r2.sum!=ro.sum)) return FALSE;
1626  return TRUE;
1627}
1628void pre_comp(poly* p,int & pn,calc_dat* c){
1629  if(!(pn))
1630    return;
1631  mac_poly* q=(mac_poly*) omalloc(pn*sizeof(mac_poly)); 
1632  int i;
1633  exp_number_builder e;
1634  for(i=0;i<pn;i++){
1635    assume(p[i]!=NULL);
1636    q[i]=new mac_poly_r();
1637    q[i]->exp=e.get_n(p[i]);
1638    q[i]->coef=nCopy(p[i]->coef);
1639   
1640    mac_poly qa=q[i];
1641    poly pa=p[i];
1642    while(pa->next!=NULL){
1643      qa->next = new mac_poly_r();
1644      qa=qa->next;
1645      pa=pa->next,
1646      qa->exp=e.get_n(pa);
1647      qa->coef=nCopy(pa->coef);
1648     
1649     
1650    }
1651    qa->next=NULL;
1652    pDelete(&p[i]);
1653  }
1654  poly* ip= (poly*)omalloc (e.n*sizeof(poly));
1655  int* ia=(int*) omalloc (e.n*sizeof(int));
1656  t2ippa(ip,ia,e);
1657  for(i=0;i<pn;i++){
1658    mac_poly mp=q[i];
1659    while(mp!=NULL){
1660      mp->exp=ia[mp->exp];
1661      mp=mp->next;
1662    }
1663   
1664  }
1665//gaus reduction start
1666  int col, row;
1667  col=0;
1668  row=0;
1669  assume(pn>0);
1670  while(row<pn-1){
1671    //row is the row where pivot should be
1672    // row== pn-1 means we have only to act on one row so no red nec.
1673    //we assume further all rows till the pn-1 row are non-zero
1674   
1675    //select column
1676    int i;
1677    col=q[row]->exp;
1678    int found_in_row=row;
1679    for(i=row;i<pn;i++){
1680      if(q[i]->exp<col){
1681        col=q[i]->exp;
1682        found_in_row=i;
1683      }
1684     
1685    }
1686    //select pivot
1687    int act_l=mac_length(q[found_in_row]);
1688    for(i=row+1;i<pn;i++){
1689      if((q[i]->exp==col)&&(mac_length(q[i])<act_l)){
1690        found_in_row=i;
1691        act_l=mac_length(q[i]);//should be optimized here
1692      }
1693    }
1694    mac_poly h=q[row];
1695    q[row]=q[found_in_row];
1696    q[found_in_row]=h;
1697
1698    //reduction
1699    for(i=row+1;i<pn;i++){
1700      if(q[i]->exp==q[row]->exp){
1701       
1702        number c1=nNeg(nCopy(q[i]->coef));
1703        number c2=q[row]->coef;
1704        //use checkcoeff later
1705        mac_mult_cons(q[i],c2);
1706        q[i]=mac_p_add_ff_qq(q[i],c1,q[row]);
1707      }
1708         
1709       
1710       
1711    }
1712    for(i=row+1;i<pn;i++){
1713      if(q[i]==NULL){
1714        q[i]=q[pn-1];
1715        pn--;
1716        if(i!=pn){i--;}
1717      }
1718    }
1719 
1720    row++;
1721  }
1722
1723
1724//gaus reduction end 
1725
1726  for(i=0;i<pn;i++){
1727    poly pa;
1728    mac_poly qa;
1729    p[i]=pLmInit(ip[q[i]->exp]);
1730    pSetCoeff(p[i],q[i]->coef);
1731    pa=p[i];
1732    qa=q[i];
1733    while(qa->next!=NULL){
1734      qa=qa->next;
1735      pa->next=pLmInit(ip[qa->exp]);
1736      pa=pa->next;
1737      pa->coef=qa->coef;
1738    }
1739    pa->next=NULL;
1740  }
1741  for(i=0;i<e.n;i++){
1742    pDelete(&ip[i]); 
1743  }
1744  omfree(ip);
1745  omfree(ia);
1746}
1747
1748static void go_on (calc_dat* c){
1749  //set limit of 1000 for multireductions, at the moment for
1750  //programming reasons
1751  int i=0;
1752  c->average_length=0;
1753  for(i=0;i<c->n;i++){
1754    c->average_length+=c->lengths[i];
1755  }
1756  c->average_length=c->average_length/c->n;
1757  i=0;
1758  poly* p=(poly*) omalloc((PAR_N+1)*sizeof(poly));//nullterminated
1759
1760  int curr_deg=-1;
1761  while(i<PAR_N){
1762    sorted_pair_node* s=top_pair(c);//here is actually chain criterium done
1763    if (!s) break;
1764    if(curr_deg>=0){
1765      if (s->deg >curr_deg) break;
1766    }
1767
1768    else curr_deg=s->deg;
1769    quick_pop_pair(c);
1770    if(s->i>=0){
1771      //replace_pair(s->i,s->j,c);
1772    if(s->i==s->j) {
1773      free_sorted_pair_node(s,c->r);
1774      continue;
1775        }
1776    }
1777    poly h;
1778    if(s->i>=0)
1779      h=ksOldCreateSpoly(c->S->m[s->i], c->S->m[s->j], NULL, c->r);
1780    else
1781      h=s->lcm_of_lm;
1782    if(s->i>=0)
1783      now_t_rep(s->j,s->i,c);
1784    number coef;
1785    int mlen=pLength(h);
1786    h=redNF2(h,c,mlen,coef,2);
1787    redTailShort(h,c->strat);
1788    nDelete(&coef);
1789
1790    free_sorted_pair_node(s,c->r);
1791    if(!h) continue;
1792    int len=pLength(h);
1793    p[i]=h;
1794   
1795    i++;
1796  }
1797  p[i]=NULL;
1798//  pre_comp(p,i,c);
1799  if(i==0){
1800    omfree(p);
1801    return;
1802  }
1803  red_object* buf=(red_object*) omalloc(i*sizeof(red_object));
1804  c->normal_forms+=i;
1805  int j;
1806  for(j=0;j<i;j++){
1807    buf[j].p=p[j];
1808    buf[j].sev=pGetShortExpVector(p[j]);
1809    buf[j].sum=NULL;
1810    buf[j].bucket = kBucketCreate(currRing);
1811    int len=pLength(p[j]);
1812    kBucketInit(buf[j].bucket,buf[j].p,len);
1813  }
1814  omfree(p);
1815  qsort(buf,i,sizeof(red_object),red_object_better_gen);
1816//    Print("\ncurr_deg:%i\n",curr_deg);
1817  if (TEST_OPT_PROT)
1818    Print("M[%i, ",i);
1819#ifdef FIND_DETERMINISTIC
1820  c->modifiedS=(BOOLEAN*) omalloc((c->strat->sl+1)*sizeof(BOOLEAN));
1821  c->expandS=(poly*) omalloc((1)*sizeof(poly));
1822  c->expandS[0]=NULL;
1823  int z2;
1824  for(z2=0;z2<=c->strat->sl;z2++)
1825    c->modifiedS[z2]=FALSE;
1826#endif
1827  multi_reduction(buf, i, c);
1828#ifdef TGB_DEBUG
1829 {
1830   int k;
1831   for(k=0;k<i;k++)
1832   {
1833     assume(kFindDivisibleByInS_easy(c->strat,buf[k])<0);
1834     int k2;
1835     for(k2=0;k2<i;k2++)
1836     {
1837       if(k==k2) continue;
1838       assume((!(p_LmDivisibleBy(buf[k].p,buf[k2].p,c->r)))||(wrp(buf[k].p),Print(" k %d k2 %d ",k,k2),wrp(buf[k2].p),FALSE));
1839     }
1840   }
1841 }
1842#endif
1843  //resort S
1844#ifdef FIND_DETERMINISTIC
1845  for(z2=0;z2<=c->strat->sl;z2++)
1846  {
1847    if (c->modifiedS[z2])
1848    {
1849      int qal;
1850      if (c->strat->lenSw)
1851        qal=c->strat->lenSw[z2];
1852      else
1853        qal=c->strat->lenS[z2];
1854      int new_pos=simple_posInS(c->strat,c->strat->S[z2],qal,c->is_char0);
1855      if (new_pos<z2)
1856      { 
1857        move_forward_in_S(z2,new_pos,c->strat,c->is_char0);
1858      }
1859    }
1860  }
1861  for(z2=0;c->expandS[z2]!=NULL;z2++)
1862  {
1863    add_to_reductors(c,c->expandS[z2],pLength(c->expandS[z2]));
1864    // PrintS("E");
1865  }
1866  omfree(c->modifiedS);
1867  c->modifiedS=NULL;
1868  omfree(c->expandS);
1869  c->expandS=NULL;
1870#endif
1871  if (TEST_OPT_PROT)
1872      Print("%i]",i); 
1873 //  for(j=0;j<i;j++){
1874//     if(buf[j].p==NULL) PrintS("\n ZERO ALERT \n");
1875//     int z;
1876//      for(z=0;z<j;z++){
1877//       if (pLmEqual(buf[z].p, buf[j].p))
1878//      PrintS("\n Critical Warning!!!! \n");
1879     
1880//     }
1881//   }
1882  int* ibuf=(int*) omalloc(i*sizeof(int));
1883  sorted_pair_node*** sbuf=(sorted_pair_node***) omalloc(i*sizeof(sorted_pair_node**));
1884  for(j=0;j<i;j++)
1885  {
1886    int len;
1887    poly p;
1888    buf[j].flatten();
1889    kBucketClear(buf[j].bucket,&p, &len);
1890    kBucketDestroy(&buf[j].bucket);
1891    // delete buf[j];
1892    //remember to free res here
1893    p=redTailShort(p, c->strat);
1894    sbuf[j]=add_to_basis_ideal_quotient(p,-1,-1,c,ibuf+j);
1895    //sbuf[j]=add_to_basis(p,-1,-1,c,ibuf+j);
1896  }
1897  int sum=0;
1898  for(j=0;j<i;j++){
1899    sum+=ibuf[j];
1900  }
1901  sorted_pair_node** big_sbuf=(sorted_pair_node**) omalloc(sum*sizeof(sorted_pair_node*));
1902  int partsum=0;
1903  for(j=0;j<i;j++)
1904  {
1905    memmove(big_sbuf+partsum, sbuf[j],ibuf[j]*sizeof(sorted_pair_node*));
1906    omfree(sbuf[j]);
1907    partsum+=ibuf[j];
1908  }
1909
1910  qsort(big_sbuf,sum,sizeof(sorted_pair_node*),pair_better_gen2);
1911  c->apairs=merge(c->apairs,c->pair_top+1,big_sbuf,sum,c);
1912  c->pair_top+=sum;
1913  clean_top_of_pair_list(c);
1914  omfree(big_sbuf);
1915  omfree(sbuf);
1916  omfree(ibuf);
1917  omfree(buf);
1918#ifdef TGB_DEBUG
1919  int z;
1920  for(z=1;z<=c->pair_top;z++)
1921  {
1922    assume(pair_better(c->apairs[z],c->apairs[z-1],c));
1923  }
1924#endif
1925  return;
1926}
1927
1928static poly redNF (poly h,kStrategy strat, int &len)
1929{
1930  len=0;
1931  if (h==NULL) return NULL;
1932  int j;
1933
1934  len=pLength(h);
1935  if (0 > strat->sl)
1936  {
1937    return h;
1938  }
1939  LObject P(h);
1940  P.SetShortExpVector();
1941  P.bucket = kBucketCreate(currRing);
1942  kBucketInit(P.bucket,P.p,len /*pLength(P.p)*/);
1943  //int max_pos=simple_posInS(strat,P.p);
1944  loop
1945    {
1946      j=kFindDivisibleByInS(strat->S,strat->sevS,strat->sl,&P);
1947      if (j>=0)
1948      {
1949        nNormalize(pGetCoeff(P.p));
1950#ifdef KDEBUG
1951        if (TEST_OPT_DEBUG)
1952        {
1953          PrintS("red:");
1954          wrp(h);
1955          PrintS(" with ");
1956          wrp(strat->S[j]);
1957        }
1958#endif
1959        number coef=kBucketPolyRed(P.bucket,strat->S[j],
1960                                   strat->lenS[j]/*pLength(strat->S[j])*/,
1961                                   strat->kNoether);
1962        nDelete(&coef);
1963        h = kBucketGetLm(P.bucket);
1964        if (h==NULL) return NULL;
1965        P.p=h;
1966        P.t_p=NULL;
1967        P.SetShortExpVector();
1968#ifdef KDEBUG
1969        if (TEST_OPT_DEBUG)
1970        {
1971          PrintS("\nto:");
1972          wrp(h);
1973          PrintLn();
1974        }
1975#endif
1976      }
1977      else
1978      {
1979        kBucketClear(P.bucket,&(P.p),&len);
1980        kBucketDestroy(&P.bucket);
1981        pNormalize(P.p);
1982        return P.p;
1983      }
1984    }
1985}
1986#endif
1987#ifdef REDTAIL_S
1988
1989static poly redNFTail (poly h,const int sl,kStrategy strat, int len)
1990{
1991  if (h==NULL) return NULL;
1992  pTest(h);
1993  if (0 > sl)
1994    return h;
1995  if (pNext(h)==NULL) return h;
1996
1997  int j;
1998  poly res=h;
1999  poly act=res;
2000  LObject P(pNext(h));
2001  pNext(res)=NULL;
2002  P.bucket = kBucketCreate(currRing);
2003  len--;
2004  h=P.p;
2005  if (len <=0) len=pLength(h);
2006  kBucketInit(P.bucket,h /*P.p*/,len /*pLength(P.p)*/);
2007  pTest(h);
2008  loop
2009  {
2010      P.p=h;
2011      P.t_p=NULL;
2012      P.SetShortExpVector();
2013      loop
2014      {
2015          j=kFindDivisibleByInS(strat->S,strat->sevS,sl,&P);
2016          if (j>=0)
2017          {
2018#ifdef REDTAIL_PROT
2019            PrintS("r");
2020#endif
2021            nNormalize(pGetCoeff(P.p));
2022#ifdef KDEBUG
2023            if (TEST_OPT_DEBUG)
2024            {
2025              PrintS("red tail:");
2026              wrp(h);
2027              PrintS(" with ");
2028              wrp(strat->S[j]);
2029            }
2030#endif
2031            number coef;
2032            pTest(strat->S[j]);
2033            coef=kBucketPolyRed(P.bucket,strat->S[j],
2034                                strat->lenS[j]/*pLength(strat->S[j])*/,strat->kNoether);
2035            pMult_nn(res,coef);
2036            nDelete(&coef);
2037            h = kBucketGetLm(P.bucket);
2038            pTest(h);
2039            if (h==NULL)
2040            {
2041#ifdef REDTAIL_PROT
2042              PrintS(" ");
2043#endif
2044              kBucketDestroy(&P.bucket);
2045              return res;
2046            }
2047            pTest(h);
2048            P.p=h;
2049            P.t_p=NULL;
2050            P.SetShortExpVector();
2051#ifdef KDEBUG
2052            if (TEST_OPT_DEBUG)
2053            {
2054              PrintS("\nto tail:");
2055              wrp(h);
2056              PrintLn();
2057            }
2058#endif
2059          }
2060          else
2061          {
2062#ifdef REDTAIL_PROT
2063            PrintS("n");
2064#endif
2065            break;
2066          }
2067      } /* end loop current mon */
2068      //   poly tmp=pHead(h /*kBucketGetLm(P.bucket)*/);
2069      //act->next=tmp;pIter(act);
2070      act->next=kBucketExtractLm(P.bucket);pIter(act);
2071      h = kBucketGetLm(P.bucket);
2072      if (h==NULL)
2073      {
2074#ifdef REDTAIL_PROT
2075        PrintS(" ");
2076#endif
2077        kBucketDestroy(&P.bucket);
2078        return res;
2079      }
2080      pTest(h);
2081  }
2082}
2083#endif
2084
2085static void do_this_spoly_stuff(int i,int j,calc_dat* c){
2086  poly f=c->S->m[i];
2087  poly g=c->S->m[j];
2088  poly h=ksOldCreateSpoly(f, g, NULL, c->r);
2089  poly hr=NULL;
2090#ifdef FULLREDUCTIONS
2091  if (h!=NULL)
2092  {
2093    int len;
2094
2095//    hr=redNF2(h,c,len);
2096//      hr=redNF(h,c->strat,len);
2097
2098    if (hr!=NULL)
2099#ifdef REDTAIL_S
2100      hr = redNFTail(hr,c->strat->sl,c->strat,len);
2101#else
2102    hr = redtailBba(hr,c->strat->sl,c->strat);
2103#endif
2104
2105  }
2106#else
2107  if (h!=NULL)
2108  {
2109    int len;
2110//    hr=redNF2(h,c,len);
2111  }
2112#endif
2113  c->normal_forms++;
2114  if (hr==NULL)
2115  {
2116    notice_miss(i, j, c);
2117
2118  }
2119  else
2120  {
2121
2122#ifdef HEAD_BIN
2123    hr=p_MoveHead(hr,c->HeadBin);
2124#endif
2125    add_to_basis(hr, i,j,c);
2126  }
2127}
2128//try to fill, return FALSE iff queue is empty
2129static void simplify(monom_poly& h, calc_dat* c){
2130  mp_array_list* F=c->F;
2131  poly_array_list* F_minus=c->F_minus;
2132  while(F)
2133  {
2134    assume(F_minus!=NULL);
2135    int i;
2136    int posm=posInMonomPolys (F->mp, F->size, h,c);
2137#ifdef TGB_DEBUG
2138#endif
2139     //for(i=0;i<F->size;i++)
2140    for(i=min(posm,F->size-1);i>=0;i--)
2141    {
2142      //      if((i>=posm)&&(F->mp[i].f!=h.f)) break;
2143      if((i<posm)&&(F->mp[i].f!=h.f)) break;
2144      if ((h.f==F->mp[i].f) &&(p_LmDivisibleBy(F->mp[i].m,h.m,c->r)))
2145      {
2146       
2147        //      Print("found");
2148       
2149          //according to the algorithm you should test (!(pIsConstant(F[i].m)))
2150          //but I think this is only because of bad formulation
2151        int j;
2152       
2153        poly lm=pLmInit(h.f);
2154        pSetCoeff(lm,nInit(1));
2155
2156        lm=pMult_mm(lm,F->mp[i].m);
2157
2158        int pos;
2159        j=-1;
2160        pos=posInPolys (F_minus->p, F_minus->size, lm,c);
2161      if((F_minus->size>pos)&&(pLmEqual(lm,F_minus->p[pos])))
2162        j=pos;
2163      if((pos>0) &&(pLmEqual(lm,F_minus->p[pos-1])))
2164        j=pos-1;
2165      assume(j!=-1);
2166      //        if(j==-1) Print("\n jAltert \n");
2167//      for(j=0;j<F_minus->size;j++)
2168//      {
2169//        if (pLmEqual(F_minus->p[j],lm))
2170//          break;
2171//      }
2172//      assume(j<F_minus->size);
2173        pDelete(&lm);
2174        if(j>=0)
2175        {
2176          pExpVectorSub(h.m,F->mp[i].m);
2177          h.f=F_minus->p[j];
2178        }
2179        break;
2180      }
2181    }
2182    F=F->next;
2183    F_minus=F_minus->next;
2184  }
2185  assume(F_minus==NULL);
2186}
2187tgb_matrix::tgb_matrix(int i, int j){
2188  n=(number**) omalloc(i*sizeof (number*));;
2189  int z;
2190  int z2;
2191  for(z=0;z<i;z++)
2192  {
2193    n[z]=(number*)omalloc(j*sizeof(number));
2194    for(z2=0;z2<j;z2++)
2195    {
2196      n[z][z2]=nInit(0);
2197    }
2198  }
2199  this->columns=j;
2200  this->rows=i;
2201  free_numbers=FALSE;
2202}
2203tgb_matrix::~tgb_matrix(){
2204  int z;
2205  for(z=0;z<rows;z++)
2206  {
2207    if(n[z])
2208    {
2209      if(free_numbers)
2210      {
2211        int z2;
2212        for(z2=0;z2<columns;z2++)
2213        {
2214          nDelete(&(n[z][z2]));
2215        }
2216      }
2217      omfree(n[z]);
2218    }
2219  }
2220  omfree(n);
2221}
2222void tgb_matrix::print(){
2223  int i;
2224  int j;
2225  Print("\n");
2226  for(i=0;i<rows;i++)
2227  {
2228    Print("(");
2229    for(j=0;j<columns;j++)
2230    {
2231      StringSetS("");
2232      n_Write(n[i][j],currRing);
2233      Print(StringAppendS(""));
2234      Print("\t");
2235    }
2236    Print(")\n");
2237  }
2238}
2239//transfers ownership of n to the matrix
2240void tgb_matrix::set(int i, int j, number n){
2241  assume(i<rows);
2242  assume(j<columns);
2243  this->n[i][j]=n;
2244}
2245int tgb_matrix::get_rows(){
2246  return rows;
2247}
2248int tgb_matrix::get_columns(){
2249  return columns;
2250}
2251number tgb_matrix::get(int i, int j){
2252  assume(i<rows);
2253  assume(j<columns);
2254  return n[i][j];
2255}
2256BOOLEAN tgb_matrix::is_zero_entry(int i, int j){
2257  return (nIsZero(n[i][j]));
2258}
2259void tgb_matrix::perm_rows(int i, int j){
2260  number* h;
2261  h=n[i];
2262  n[i]=n[j];
2263  n[j]=h;
2264}
2265int tgb_matrix::min_col_not_zero_in_row(int row){
2266  int i;
2267  for(i=0;i<columns;i++)
2268  {
2269    if(!(nIsZero(n[row][i])))
2270      return i;
2271  }
2272  return columns;//error code
2273}
2274int tgb_matrix::next_col_not_zero(int row,int pre){
2275  int i;
2276  for(i=pre+1;i<columns;i++)
2277  {
2278    if(!(nIsZero(n[row][i])))
2279      return i;
2280  }
2281  return columns;//error code
2282}
2283BOOLEAN tgb_matrix::zero_row(int row){
2284  int i;
2285  for(i=0;i<columns;i++)
2286  {
2287    if(!(nIsZero(n[row][i])))
2288      return FALSE;
2289  }
2290  return TRUE;
2291}
2292int tgb_matrix::non_zero_entries(int row){
2293  int i;
2294  int z=0;
2295  for(i=0;i<columns;i++)
2296  {
2297    if(!(nIsZero(n[row][i])))
2298      z++;
2299  }
2300  return z;
2301}
2302//row add_to=row add_to +row summand*factor
2303void tgb_matrix::add_lambda_times_row(int add_to,int summand,number factor){
2304  int i;
2305  for(i=0;i<columns;i++){
2306    if(!(nIsZero(n[summand][i])))
2307    {
2308      number n1=n[add_to][i];
2309      number n2=nMult(factor,n[summand][i]);
2310      n[add_to][i]=nAdd(n1,n2);
2311      nDelete(&n1);
2312      nDelete(&n2);
2313    }
2314  }
2315}
2316void tgb_matrix::mult_row(int row,number factor){
2317  if (nIsOne(factor))
2318    return;
2319  int i;
2320  for(i=0;i<columns;i++){
2321    if(!(nIsZero(n[row][i])))
2322    {
2323      number n1=n[row][i];
2324      n[row][i]=nMult(n1,factor);
2325      nDelete(&n1);
2326    }
2327  }
2328}
2329void tgb_matrix::free_row(int row, BOOLEAN free_non_zeros){
2330  int i;
2331  for(i=0;i<columns;i++)
2332    if((free_non_zeros)||(!(nIsZero(n[row][i]))))
2333      nDelete(&(n[row][i]));
2334  omfree(n[row]);
2335  n[row]=NULL;
2336}
2337
2338
2339tgb_sparse_matrix::tgb_sparse_matrix(int i, int j, ring rarg){
2340  mp=(mac_poly*) omalloc(i*sizeof (mac_poly));;
2341  int z;
2342  int z2;
2343  for(z=0;z<i;z++)
2344  {
2345    mp[z]=NULL;
2346  }
2347  this->columns=j;
2348  this->rows=i;
2349  free_numbers=FALSE;
2350  r=rarg;
2351}
2352tgb_sparse_matrix::~tgb_sparse_matrix(){
2353  int z;
2354  for(z=0;z<rows;z++)
2355  {
2356    if(mp[z])
2357    {
2358      if(free_numbers)
2359      {
2360        mac_destroy(mp[z]);
2361      }
2362      else {
2363        while(mp[z])
2364        {
2365         
2366          mac_poly next=mp[z]->next;
2367          delete mp[z];
2368          mp[z]=next;
2369        }
2370      }
2371    }
2372  }
2373  omfree(mp);
2374}
2375int row_cmp_gen(const void* a, const void* b){
2376  const mac_poly ap= *((mac_poly*) a);
2377  const mac_poly bp=*((mac_poly*) b);
2378  if (ap==NULL) return 1;
2379  if (bp==NULL) return -1;
2380  if (ap->exp<bp->exp) return -1;
2381  return 1;
2382}
2383void tgb_sparse_matrix::sort_rows(){
2384  qsort(mp,rows,sizeof(mac_poly),row_cmp_gen);
2385}
2386void tgb_sparse_matrix::print(){
2387  int i;
2388  int j;
2389  Print("\n");
2390  for(i=0;i<rows;i++)
2391  {
2392    Print("(");
2393    for(j=0;j<columns;j++)
2394    {
2395      StringSetS("");
2396      number n=get(i,j);
2397      n_Write(n,currRing);
2398      Print(StringAppendS(""));
2399      Print("\t");
2400    }
2401    Print(")\n");
2402  }
2403}
2404//transfers ownership of n to the matrix
2405void tgb_sparse_matrix::set(int i, int j, number n){
2406  assume(i<rows);
2407  assume(j<columns);
2408  mac_poly* set_this=&mp[i];
2409  //  while(((*set_this)!=NULL)&&((*set_this)­>exp<j))
2410  while(((*set_this)!=NULL) && ((*set_this)->exp<j))
2411    set_this=&((*set_this)->next);
2412
2413  if (((*set_this)==NULL)||((*set_this)->exp>j))
2414  {
2415    if (nIsZero(n)) return;
2416    mac_poly old=(*set_this);
2417    (*set_this)=new mac_poly_r();
2418    (*set_this)->exp=j;
2419    (*set_this)->coef=n;
2420    (*set_this)->next=old;
2421    return;
2422  }
2423  assume((*set_this)->exp==j);
2424  if(!nIsZero(n))
2425  {
2426    nDelete(&(*set_this)->coef);
2427    (*set_this)->coef=n;
2428  }
2429  else
2430  {
2431    nDelete(&(*set_this)->coef);
2432    mac_poly dt=(*set_this);
2433    (*set_this)=dt->next;
2434    delete dt;
2435   
2436   
2437  }
2438  return;
2439}
2440
2441
2442
2443int tgb_sparse_matrix::get_rows(){
2444  return rows;
2445}
2446int tgb_sparse_matrix::get_columns(){
2447  return columns;
2448}
2449number tgb_sparse_matrix::get(int i, int j){
2450  assume(i<rows);
2451  assume(j<columns);
2452  mac_poly r=mp[i];
2453  while((r!=NULL)&&(r->exp<j))
2454    r=r->next;
2455  if ((r==NULL)||(r->exp>j))
2456  {
2457    number n=nInit(0);
2458    return n;
2459  }
2460  assume(r->exp==j);
2461  return r->coef;
2462}
2463BOOLEAN tgb_sparse_matrix::is_zero_entry(int i, int j){
2464  assume(i<rows);
2465  assume(j<columns);
2466  mac_poly r=mp[i];
2467  while((r!=NULL)&&(r->exp<j))
2468    r=r->next;
2469  if ((r==NULL)||(r->exp>j))
2470  {
2471    return TRUE;
2472  }
2473  assume(!nIsZero(r->coef));
2474  assume(r->exp==j);
2475  return FALSE;
2476 
2477}
2478
2479int tgb_sparse_matrix::min_col_not_zero_in_row(int row){
2480  if(mp[row]!=NULL)
2481  {
2482    assume(!nIsZero(mp[row]->coef));
2483    return mp[row]->exp;
2484  }
2485  else
2486
2487 
2488  return columns;//error code
2489}
2490int tgb_sparse_matrix::next_col_not_zero(int row,int pre){ 
2491  mac_poly r=mp[row];
2492  while((r!=NULL)&&(r->exp<=pre))
2493    r=r->next;
2494  if(r!=NULL)
2495  {
2496    assume(!nIsZero(r->coef));
2497    return r->exp;
2498  }
2499  return columns;//error code
2500}
2501BOOLEAN tgb_sparse_matrix::zero_row(int row){
2502  assume((mp[row]==NULL)||(!nIsZero(mp[row]->coef)));
2503  if (mp[row]==NULL)
2504    return TRUE;
2505  else
2506    return FALSE;
2507}
2508void tgb_sparse_matrix::row_normalize(int row){
2509  if (!rField_has_simple_inverse(r))  /* Z/p, GF(p,n), R, long R/C */
2510  {
2511    mac_poly m=mp[row];
2512        while (m!=NULL)
2513        {
2514          if (currRing==r) {nTest(m->coef);}
2515          n_Normalize(m->coef,r);
2516          m=m->next;
2517        }
2518  }
2519}
2520int tgb_sparse_matrix::non_zero_entries(int row){
2521
2522  return mac_length(mp[row]);
2523}
2524//row add_to=row add_to +row summand*factor
2525void tgb_sparse_matrix::add_lambda_times_row(int add_to,int summand,number factor){
2526  mp[add_to]= mac_p_add_ff_qq(mp[add_to], factor,mp[summand]);
2527
2528}
2529void tgb_sparse_matrix::mult_row(int row,number factor){
2530  if (nIsZero(factor))
2531  {
2532    mac_destroy(mp[row]);
2533    mp[row]=NULL;
2534   
2535    return;
2536  }
2537  mac_mult_cons(mp[row],factor);
2538}
2539void tgb_sparse_matrix::free_row(int row, BOOLEAN free_non_zeros){
2540  if(free_non_zeros)
2541    mac_destroy(mp[row]);
2542  else
2543  {
2544    while(mp[row])
2545    {
2546     
2547      mac_poly next=mp[row]->next;
2548      delete mp[row];
2549      mp[row]=next;
2550    }
2551  }
2552  mp[row]=NULL;
2553}
2554//transfers ownership of m to mat
2555void init_with_mac_poly(tgb_sparse_matrix* mat, int row, mac_poly m){
2556  assume(mat->mp[row]==NULL);
2557  mat->mp[row]=m;
2558#ifdef TGB_DEBUG
2559  mac_poly r=m;
2560  while(r){
2561    assume(r->exp<mat->columns);
2562    r=r->next;
2563  }
2564#endif
2565}
2566poly free_row_to_poly(tgb_sparse_matrix* mat, int row, poly* monoms, int monom_index){
2567  poly p=NULL;
2568  poly* set_this=&p;
2569  mac_poly r=mat->mp[row];
2570  mat->mp[row]=NULL;
2571  while(r)
2572  {
2573    (*set_this)=pLmInit(monoms[monom_index-1-r->exp]);
2574    pSetCoeff((*set_this),r->coef);
2575    set_this=&((*set_this)->next);
2576    r=r->next;
2577   
2578  }
2579  return p;
2580
2581}
2582
2583void simple_gauss(tgb_sparse_matrix* mat, calc_dat* c){
2584  int col, row;
2585  int* row_cache=(int*) omalloc(mat->get_rows()*sizeof(int));
2586  col=0;
2587  row=0;
2588  int i;
2589  int pn=mat->get_rows();
2590  int matcol=mat->get_columns();
2591  int* area=(int*) omalloc(sizeof(int)*((matcol-1)/bundle_size+1));
2592  const int max_area_index=(matcol-1)/bundle_size;
2593    //rows are divided in areas
2594  //if row begins with columns col, it is located in [area[col/bundle_size],area[col/bundle_size+1]-1]
2595  assume(pn>0);
2596  //first clear zeroes
2597  for(i=0;i<pn;i++)
2598  {
2599    if(mat->zero_row(i))
2600    {
2601      mat->perm_rows(i,pn-1);
2602      pn--;
2603      if(i!=pn){i--;}
2604    }
2605 
2606  }
2607  mat->sort_rows();
2608  for(i=0;i<pn;i++)
2609  {
2610      row_cache[i]=mat->min_col_not_zero_in_row(i);
2611      // Print("row_cache:%d\n",row_cache[i]);
2612  }
2613  int last_area=-1;
2614  for(i=0;i<pn;i++)
2615  {
2616    int this_area=row_cache[i]/bundle_size;
2617    assume(this_area>=last_area);
2618    if(this_area>last_area)
2619    {
2620      int j;
2621      for(j=last_area+1;j<=this_area;j++)
2622        area[j]=i;
2623      last_area=this_area;
2624    }
2625  }
2626  for(i=last_area+1;i<=max_area_index;i++)
2627  {
2628    area[i]=pn;
2629  }
2630  while(row<pn-1){
2631    //row is the row where pivot should be
2632    // row== pn-1 means we have only to act on one row so no red nec.
2633    //we assume further all rows till the pn-1 row are non-zero
2634   
2635    //select column
2636   
2637    //col=mat->min_col_not_zero_in_row(row);
2638    int max_in_area;
2639    {
2640      int tai=row_cache[row]/bundle_size;
2641      assume(tai<=max_area_index);
2642      if(tai==max_area_index)
2643        max_in_area=pn-1;
2644      else
2645        max_in_area=area[tai+1]-1;
2646    }
2647    assume(row_cache[row]==mat->min_col_not_zero_in_row(row));
2648    col=row_cache[row];
2649
2650   
2651    assume(col!=matcol);
2652    int found_in_row;
2653   
2654    found_in_row=row;
2655    BOOLEAN must_reduce=FALSE;
2656    assume(pn<=mat->get_rows());
2657    for(i=row+1;i<=max_in_area;i++){
2658      int first;//=mat->min_col_not_zero_in_row(i);
2659      assume(row_cache[i]==mat->min_col_not_zero_in_row(i));
2660      first=row_cache[i];
2661      assume(first!=matcol);
2662      if(first<col)
2663      {
2664        col=first;
2665        found_in_row=i;
2666        must_reduce=FALSE;
2667      }
2668      else {
2669        if(first==col)
2670          must_reduce=TRUE;
2671      }
2672    }
2673    //select pivot
2674    int act_l=mat->non_zero_entries(found_in_row);
2675    for(i=found_in_row+1;i<=max_in_area;i++){
2676      assume(mat->min_col_not_zero_in_row(i)>=col);
2677      int first;
2678      assume(row_cache[i]==mat->min_col_not_zero_in_row(i));
2679      first=row_cache[i];
2680      assume(first!=matcol);
2681      //      if((!(mat->is_zero_entry(i,col)))&&(mat->non_zero_entries(i)<act_l))
2682      int nz;
2683      if((row_cache[i]==col)&&((nz=mat->non_zero_entries(i))<act_l))
2684      {
2685        found_in_row=i;
2686        act_l=nz;
2687      }
2688
2689    }
2690
2691    mat->perm_rows(row,found_in_row);
2692    int h=row_cache[row];
2693    row_cache[row]=row_cache[found_in_row];
2694    row_cache[found_in_row]=h;
2695
2696
2697
2698    if(!must_reduce){
2699      row++;
2700      continue;
2701    }
2702    //reduction
2703    //must extract content and normalize here
2704    mat->row_normalize(row);
2705
2706    //for(i=row+1;i<pn;i++){
2707    for(i=max_in_area;i>row;i--)
2708    {
2709      int col_area_index=col/bundle_size;
2710      assume(col_area_index<=max_area_index);
2711      assume(mat->min_col_not_zero_in_row(i)>=col);
2712      int first;
2713      assume(row_cache[i]==mat->min_col_not_zero_in_row(i));
2714      first=row_cache[i];
2715      assume(first!=matcol);
2716      if(row_cache[i]==col)
2717      {
2718       
2719        number c1=nNeg(nCopy(mat->get(i,col)));
2720        number c2=mat->get(row,col);
2721        number n1=c1;
2722        number n2=c2;
2723
2724        ksCheckCoeff(&n1,&n2);
2725        nDelete(&c1);
2726        mat->mult_row(i,n2);
2727        mat->add_lambda_times_row(i,row,n1);
2728        nDelete(&n1);
2729        nDelete(&n2);
2730        assume(mat->is_zero_entry(i,col));
2731        row_cache[i]=mat->min_col_not_zero_in_row(i);
2732        assume(mat->min_col_not_zero_in_row(i)>col);
2733        if(row_cache[i]==matcol)
2734        {
2735          int index;
2736          index=i;
2737          int last_in_area;
2738          int this_cai=col_area_index;
2739          while(this_cai<max_area_index)
2740          {
2741            last_in_area=area[this_cai+1]-1;
2742            int h_c=row_cache[last_in_area];
2743            row_cache[last_in_area]=row_cache[index];
2744            row_cache[index]=h_c;
2745            mat->perm_rows(index,last_in_area);
2746            index=last_in_area;
2747            this_cai++;
2748            area[this_cai]--;
2749          }
2750          mat->perm_rows(index,pn-1);
2751          row_cache[index]=row_cache[pn-1];
2752          row_cache[pn-1]=matcol;
2753          pn--;
2754        }
2755        else 
2756        {
2757          int index;
2758          index=i;
2759          int last_in_area;
2760          int this_cai=col_area_index;
2761          int final_cai=row_cache[index]/bundle_size;
2762          assume(final_cai<=max_area_index);
2763          while(this_cai<final_cai)
2764          {
2765            last_in_area=area[this_cai+1]-1;
2766            int h_c=row_cache[last_in_area];
2767            row_cache[last_in_area]=row_cache[index];
2768            row_cache[index]=h_c;
2769            mat->perm_rows(index,last_in_area);
2770            index=last_in_area;
2771            this_cai++;
2772            area[this_cai]--;
2773          }
2774        }
2775      }
2776      else
2777        assume(mat->min_col_not_zero_in_row(i)>col);
2778    }
2779
2780//     for(i=row+1;i<pn;i++)
2781//     {
2782//       assume(mat->min_col_not_zero_in_row(i)==row_cache[i]);
2783//       // if(mat->zero_row(i))
2784//       assume(matcol==mat->get_columns());
2785//       if(row_cache[i]==matcol)
2786//       {
2787//      assume(mat->zero_row(i));
2788//      mat->perm_rows(i,pn-1);
2789//      row_cache[i]=row_cache[pn-1];
2790//      row_cache[pn-1]=matcol;
2791//      pn--;
2792//      if(i!=pn){i--;}
2793//       }
2794//     }
2795#ifdef TGB_DEBUG
2796  {
2797  int last=-1;
2798  for(i=0;i<pn;i++)
2799  {
2800    int act=mat->min_col_not_zero_in_row(i);
2801    assume(act>last);
2802   
2803  }
2804  for(i=pn;i<mat->get_rows();i++)
2805  {
2806    assume(mat->zero_row(i));
2807   
2808  }
2809 
2810
2811  }
2812#endif
2813    row++;
2814  }
2815  omfree(area);
2816  omfree(row_cache);
2817}
2818void simple_gauss2(tgb_matrix* mat){
2819  int col, row;
2820  col=0;
2821  row=0;
2822  int i;
2823  int pn=mat->get_rows();
2824  assume(pn>0);
2825  //first clear zeroes
2826//   for(i=0;i<pn;i++)
2827//   {
2828//     if(mat->zero_row(i))
2829//     {
2830//       mat->perm_rows(i,pn-1);
2831//       pn--;
2832//       if(i!=pn){i--;}
2833//     }
2834//   }
2835  while((row<pn-1)&&(col<mat->get_columns())){
2836    //row is the row where pivot should be
2837    // row== pn-1 means we have only to act on one row so no red nec.
2838    //we assume further all rows till the pn-1 row are non-zero
2839   
2840    //select column
2841   
2842    //    col=mat->min_col_not_zero_in_row(row);
2843    assume(col!=mat->get_columns());
2844    int found_in_row=-1;
2845   
2846    //    found_in_row=row;
2847    assume(pn<=mat->get_rows());
2848    for(i=row;i<pn;i++)
2849    {
2850      //    int first=mat->min_col_not_zero_in_row(i);
2851      //  if(first<col)
2852      if(!(mat->is_zero_entry(i,col))){
2853       
2854        found_in_row=i;
2855        break;
2856      }
2857    }
2858    if(found_in_row!=-1)
2859    {
2860    //select pivot
2861      int act_l=mat->non_zero_entries(found_in_row);
2862      for(i=i+1;i<pn;i++)
2863      {
2864        int vgl;
2865        assume(mat->min_col_not_zero_in_row(i)>=col);
2866        if((!(mat->is_zero_entry(i,col)))&&((vgl=mat->non_zero_entries(i))<act_l))
2867        {
2868          found_in_row=i;
2869          act_l=vgl;
2870        }
2871       
2872      }
2873      mat->perm_rows(row,found_in_row);
2874     
2875     
2876      //reduction
2877      for(i=row+1;i<pn;i++){
2878        assume(mat->min_col_not_zero_in_row(i)>=col);
2879        if(!(mat->is_zero_entry(i,col)))
2880        {
2881         
2882          number c1=nNeg(nCopy(mat->get(i,col)));
2883          number c2=mat->get(row,col);
2884          number n1=c1;
2885          number n2=c2;
2886         
2887          ksCheckCoeff(&n1,&n2);
2888          nDelete(&c1);
2889          mat->mult_row(i,n2);
2890          mat->add_lambda_times_row(i,row,n1);
2891          assume(mat->is_zero_entry(i,col));
2892         
2893        } 
2894        assume(mat->min_col_not_zero_in_row(i)>col);
2895      }
2896      row++;
2897    }
2898    col++;
2899    // for(i=row+1;i<pn;i++)
2900//     {
2901//       if(mat->zero_row(i))
2902//       {
2903//      mat->perm_rows(i,pn-1);
2904//      pn--;
2905//      if(i!=pn){i--;}
2906//       }
2907//     }
2908
2909  }
2910}
2911
2912static tgb_matrix* build_matrix(poly* p,int p_index,poly* done, int done_index, calc_dat* c){
2913  tgb_matrix* t=new tgb_matrix(p_index,done_index);
2914  int i, pos;
2915  //  Print("\n 0:%s\n",pString(done[done_index-1]));
2916  //Print("\n 1:%s\n",pString(done[done_index-2]));
2917  assume((!(pLmEqual(done[done_index-1],done[done_index-2]))));
2918#ifdef TGB_DEGUG
2919  for(i=0;i<done_index;i++)
2920  {
2921    int j;
2922    for(j=0;j<i;j++)
2923    {
2924      assume((!(pLmEqual(done[i],done[j]))));
2925    }
2926  }
2927#endif
2928  for(i=0;i<p_index;i++)
2929  { 
2930    // Print("%i ter Eintrag:%s\n",i,pString(p[i]));
2931    poly p_i=p[i];
2932    while(p_i)
2933    {
2934
2935      int v=-1;
2936      pos=posInPolys (done, done_index, p_i,c);
2937      if((done_index>pos)&&(pLmEqual(p_i,done[pos])))
2938        v=pos;
2939      if((pos>0) &&(pLmEqual(p_i,done[pos-1])))
2940        v=pos-1;
2941      assume(v!=-1);
2942      //v is ascending ordered, we need descending order
2943      v=done_index-1-v;
2944      number nt=t->get(i,v);
2945      nDelete(&nt);
2946      t->set(i,v,nCopy(p_i->coef));
2947      p_i=p_i->next;
2948    }
2949  }
2950  return t;
2951}
2952static tgb_sparse_matrix* build_sparse_matrix(poly* p,int p_index,poly* done, int done_index, calc_dat* c){
2953  tgb_sparse_matrix* t=new tgb_sparse_matrix(p_index,done_index,c->r);
2954  int i, pos;
2955  //  Print("\n 0:%s\n",pString(done[done_index-1]));
2956  //Print("\n 1:%s\n",pString(done[done_index-2]));
2957  //  assume((!(pLmEqual(done[done_index-1],done[done_index-2]))));
2958#ifdef TGB_DEGUG
2959  for(i=0;i<done_index;i++)
2960  {
2961    int j;
2962    for(j=0;j<i;j++)
2963    {
2964      assume((!(pLmEqual(done[i],done[j]))));
2965    }
2966  }
2967#endif
2968  for(i=0;i<p_index;i++)
2969  { 
2970    // Print("%i ter Eintrag:%s\n",i,pString(p[i]));
2971    mac_poly m=NULL;
2972    mac_poly* set_this=&m;
2973    poly p_i=p[i];
2974    while(p_i)
2975    {
2976
2977      int v=-1;
2978      pos=posInPolys (done, done_index, p_i,c);
2979      if((done_index>pos)&&(pLmEqual(p_i,done[pos])))
2980        v=pos;
2981      if((pos>0) &&(pLmEqual(p_i,done[pos-1])))
2982        v=pos-1;
2983      assume(v!=-1);
2984      //v is ascending ordered, we need descending order
2985      v=done_index-1-v;
2986      (*set_this)=new mac_poly_r();
2987      (*set_this)->exp=v;
2988       
2989      (*set_this)->coef=nCopy(p_i->coef);
2990       set_this=&(*set_this)->next;
2991       p_i=p_i->next;
2992
2993    }
2994    init_with_mac_poly(t,i,m);
2995  }
2996  return t;
2997}
2998
2999
3000static int retranslate(poly* m,tgb_sparse_matrix* mat,poly* done, calc_dat* c){
3001  int i;
3002  int m_index=0;
3003  for(i=0;i<mat->get_rows();i++)
3004  {
3005    if(mat->zero_row(i))
3006    {
3007      mat->free_row(i);
3008      continue;
3009    }
3010    m[m_index++]= free_row_to_poly(mat, i, done, mat->get_columns());
3011
3012  }
3013
3014  delete mat;
3015  return m_index;
3016
3017}
3018
3019//returns m_index and destroys mat
3020static int retranslate(poly* m,tgb_matrix* mat,poly* done, calc_dat* c){
3021  int i;
3022  int m_index=0;
3023  for(i=0;i<mat->get_rows();i++)
3024  {
3025    if(mat->zero_row(i))
3026    {
3027      mat->free_row(i);
3028      continue;
3029    }
3030   
3031    m[m_index]=pInit();
3032    int v=mat->min_col_not_zero_in_row(i);
3033    //v=done_index-1-pos; => pos=done_index-1-v=mat->get_columns()-1-v
3034    int pos=mat->get_columns()-1-v;
3035    int* ev=(int*) omalloc((c->r->N+1)*sizeof(int));
3036    pGetExpV(done[pos],ev);
3037    pSetExpV(m[m_index],ev);
3038    omfree(ev);
3039   
3040    poly p=m[m_index];
3041    pSetCoeff(p,mat->get(i,v));
3042    while((v=mat->next_col_not_zero(i,v))!=mat->get_columns())
3043    {
3044      poly pn=pInit();
3045     
3046      //v=done_index-1-pos; => pos=done_index-1-v=mat->get_columns()-1-v
3047      pos=mat->get_columns()-1-v;
3048      ev=(int*) omalloc((c->r->N+1)*sizeof(int));
3049      pGetExpV(done[pos],ev);
3050      pSetExpV(pn,ev);
3051      omfree(ev);
3052      pSetCoeff(pn,mat->get(i,v));
3053      p->next=pn;
3054      p=pn;
3055    }
3056    p->next=NULL;
3057    mat->free_row(i, FALSE);
3058    m_index++;
3059  }
3060
3061  delete mat;
3062  return m_index;
3063
3064}
3065static void go_on_F4 (calc_dat* c){
3066  //set limit of 1000 for multireductions, at the moment for
3067  //programming reasons
3068  int max_par;
3069  if (c->is_homog)
3070    max_par=PAR_N_F4;
3071  else
3072    max_par=200;
3073  int done_size=max_par*2;
3074  poly* done=(poly*) omalloc(done_size*sizeof(poly));
3075  int done_index=0; //done_index must always be smaller than done_size
3076  int chosen_size=max_par*2;
3077  monom_poly* chosen=(monom_poly*) omalloc(chosen_size*sizeof(monom_poly));
3078  int chosen_index=0;
3079  //  monom_poly* vgl=(monom_poly*) omalloc(chosen_size*sizeof(monom_poly));
3080  int i=0;
3081  c->average_length=0;
3082  for(i=0;i<c->n;i++){
3083    c->average_length+=c->lengths[i];
3084  }
3085  c->average_length=c->average_length/c->n;
3086  i=0;
3087  poly* p;
3088  int nfs=0;
3089  int curr_deg=-1;
3090
3091  //choose pairs and preprocess symbolically
3092  while(chosen_index<max_par)
3093  {
3094   
3095    //    sorted_pair_node* s=c->apairs[c->pair_top];
3096    sorted_pair_node* s;
3097    if(c->pair_top>=0)
3098      s=top_pair(c);//here is actually chain criterium done
3099    else
3100      s=NULL;
3101    if (!s) break;
3102    nfs++;
3103    if(curr_deg>=0)
3104    {
3105      if (s->deg >curr_deg) break;
3106    }
3107
3108    else curr_deg=s->deg;
3109    quick_pop_pair(c);
3110    if(s->i>=0)
3111    {
3112      //replace_pair(s->i,s->j,c);
3113      if(s->i==s->j) 
3114      {
3115        free_sorted_pair_node(s,c->r);
3116        continue;
3117      }
3118    }
3119    assume(s->i>=0);
3120    monom_poly h;
3121    BOOLEAN only_free=FALSE;
3122    if(s->i>=0)
3123    {
3124     
3125      poly lcm=pOne();
3126     
3127      pLcm(c->S->m[s->i], c->S->m[s->j], lcm);
3128      pSetm(lcm);
3129      assume(lcm!=NULL);
3130      poly factor1=pCopy(lcm);
3131      pExpVectorSub(factor1,c->S->m[s->i]);
3132      poly factor2=pCopy(lcm);
3133      pExpVectorSub(factor2,c->S->m[s->j]);
3134
3135      if(done_index>=done_size)
3136      {
3137        done_size+=max_par;
3138        done=(poly*) omrealloc(done,done_size*sizeof(poly));
3139      }
3140      done[done_index++]=lcm;
3141      if(chosen_index+1>=chosen_size)
3142      {
3143        //max_par must be greater equal 2
3144        chosen_size+=max(max_par,2);
3145        chosen=(monom_poly*) omrealloc(chosen,chosen_size*sizeof(monom_poly));
3146      }
3147      h.f=c->S->m[s->i];
3148      h.m=factor1;
3149      chosen[chosen_index++]=h;
3150      h.f=c->S->m[s->j];
3151      h.m=factor2;
3152      chosen[chosen_index++]=h;
3153    }
3154    else
3155    {
3156      if(chosen_index>=chosen_size)
3157      {
3158        chosen_size+=max_par;
3159        chosen=(monom_poly*) omrealloc(chosen,chosen_size*sizeof(monom_poly));
3160      }
3161      h.f=s->lcm_of_lm;
3162      h.m=pOne();
3163      //pSetm(h.m); done by pOne
3164      chosen[chosen_index++]=h;
3165      //must carefull remember to destroy such a h;
3166      poly_list_node* next=c->to_destroy;
3167     
3168      c->to_destroy=(poly_list_node*) omalloc(sizeof(poly_list_node));
3169      c->to_destroy->p=h.f;
3170      c->to_destroy->next=next;
3171      only_free=TRUE;
3172    }
3173
3174    if(s->i>=0)
3175      now_t_rep(s->j,s->i,c);
3176
3177    if(!(only_free))
3178      free_sorted_pair_node(s,c->r);
3179    else
3180      omfree(s);
3181   
3182 
3183
3184  }
3185  c->normal_forms+=nfs;
3186  if (TEST_OPT_PROT)
3187      Print("M[%i, ",nfs);
3188  //next Step, simplify all pairs
3189  for(i=0;i<chosen_index;i++)
3190  {
3191    //    PrintS("simplifying ");
3192    //Print("from %s",pString(chosen[i].m));
3193    //Print(", %s", pString(chosen[i].f));
3194     simplify(chosen[i],c);
3195    //Print(" to %s",pString(chosen[i].m));
3196    //Print(", %s \n", pString(chosen[i].f));
3197  }
3198 
3199  //next Step remove duplicate entries
3200  qsort(chosen,chosen_index,sizeof(monom_poly),monom_poly_crit);
3201  int pos=0;
3202  for(i=1;i<chosen_index;i++)
3203  {
3204    if(((chosen[i].f!=chosen[pos].f))||(!(pLmEqual(chosen[i].m,chosen[pos].m))))
3205      chosen[++pos]=chosen[i];
3206    else pDelete(&(chosen[i].m));
3207  }
3208  if(chosen_index>0)
3209    chosen_index=pos+1;
3210  //next step process polys
3211  int p_size=2*chosen_index;
3212  int p_index=0;
3213  p=(poly*) omalloc(p_size*sizeof(poly));
3214  for(p_index=0;p_index<chosen_index;p_index++)
3215  {
3216    p[p_index]=ppMult_mm(chosen[p_index].f,chosen[p_index].m);
3217  }
3218
3219  qsort(done, done_index,sizeof(poly),pLmCmp_func);
3220  pos=0;
3221  //Print("Done_index:%i",done_index);
3222  if(done_index>0)
3223  {
3224    pTest(done[0]);
3225  }
3226  for(i=1;i<done_index;i++)
3227  {
3228    pTest(done[i]);
3229    if((!(pLmEqual(done[i],done[pos]))))
3230      done[++pos]=done[i];
3231    else pDelete(&(done[i]));
3232  }
3233  if(done_index>0)
3234    done_index=pos+1;
3235#ifdef TGB_DEBUG
3236  for(i=0;i<done_index;i++)
3237  {
3238    int j;
3239    for(j=0;j<i;j++)
3240    {
3241      assume((!pLmEqual(done[j],done[i])));
3242    }
3243  }
3244#endif
3245#ifdef TGB_DEBUG
3246  for(i=0;i<done_index;i++)
3247  {
3248    pTest(done[i]);
3249  }
3250#endif
3251  poly* m;
3252  int m_index=0;
3253  int m_size=0;
3254  for(i=0;i<p_index;i++)
3255  {
3256    m_size+=pLength(p[i]);
3257  }
3258  m=(poly*) omalloc(m_size*sizeof(poly));
3259  //q=(poly*) omalloc(m_size*sizeof(poly));
3260
3261 
3262
3263  for(i=0;i<p_index;i++)
3264  {
3265
3266    poly p_i=p[i];
3267
3268    pTest(p[i]);
3269
3270    while(p_i)
3271    {
3272
3273      m[m_index]=pLmInit(p_i);
3274
3275      pSetCoeff(m[m_index],nInit(1));
3276
3277       p_i=p_i->next;
3278
3279      m_index++;
3280
3281    }
3282  }
3283
3284  int q_size=m_index;
3285  poly* q=(poly*) omalloc(q_size*sizeof(poly));
3286  int q_index=0;
3287  //next Step additional reductors
3288
3289  while(m_index>0)
3290  {
3291#ifdef TGB_DEBUG
3292     
3293      for(i=0;i<done_index;i++)
3294      {
3295        pTest(done[i]);
3296      }
3297#endif
3298
3299    qsort(m, m_index,sizeof(poly),pLmCmp_func);
3300
3301   
3302    pos=0;
3303    #ifdef TGB_DEBUG
3304     
3305      for(i=0;i<done_index;i++)
3306      {
3307       
3308        pTest(done[i]);
3309      }
3310#endif
3311    for(i=1;i<m_index;i++)
3312    {
3313      pTest(m[i]);
3314      pTest(m[pos]);
3315      if((!(pLmEqual(m[i],m[pos]))))
3316        m[++pos]=m[i];
3317      else pDelete(&(m[i]));
3318    }
3319    if(m_index>1)
3320      m_index=pos+1;
3321    if(done_size<done_index+m_index)
3322    {
3323      done_size=done_index+2*m_index;
3324      done=(poly*) omrealloc(done,done_size*sizeof(poly));
3325    }
3326    if(chosen_size<chosen_index+m_index)
3327    {
3328      chosen_size=chosen_index+2*m_index;
3329      chosen=(monom_poly*) omrealloc(chosen,chosen_size*sizeof(monom_poly));
3330    }
3331    q_index=0;
3332    if(q_size<m_index)
3333    {
3334      q_size=2*m_index;
3335      omfree(q);
3336      q=(poly*) omalloc(q_size*sizeof(poly));
3337    }
3338
3339    for(i=0;i<m_index;i++)
3340    {
3341
3342#ifdef TGB_DEBUG
3343      {
3344        int my_i;
3345        for(my_i=0;my_i<done_index;my_i++)
3346        {
3347          int my_j;
3348          for(my_j=0;my_j<my_i;my_j++)
3349          {
3350            assume((!pLmEqual(done[my_j],done[my_i])));
3351          }
3352        }
3353      }
3354#endif
3355      BOOLEAN in_done=FALSE;
3356      pTest(m[i]);
3357
3358      pos=posInPolys (done, done_index, m[i],c);
3359#ifdef TGB_DEBUG
3360      {
3361        int my_i;
3362        for (my_i=0;my_i<done_index;my_i++)
3363          pTest(done[my_i]);
3364      }
3365#endif     
3366      if(((done_index>pos)&&(pLmEqual(m[i],done[pos]))) ||(pos>0) &&(pLmEqual(m[i],done[pos-1])))
3367        in_done=TRUE;
3368      if (!(in_done))
3369      {
3370       
3371        int S_pos=kFindDivisibleByInS_easy(c->strat,m[i], pGetShortExpVector(m[i]));
3372        if(S_pos>=0)
3373        {
3374          monom_poly h;
3375          h.f=c->strat->S[S_pos];
3376          h.m=pOne();
3377          int* ev=(int*) omalloc((c->r->N+1)*sizeof(int));
3378          pGetExpV(m[i],ev);
3379          pSetExpV(h.m,ev);
3380          omfree(ev);
3381          pExpVectorSub(h.m,c->strat->S[S_pos]);
3382          simplify(h,c);
3383          q[q_index]=ppMult_mm(h.f,h.m);
3384          chosen[chosen_index++]=h;
3385          q_index++;
3386        }
3387        pTest(m[i]);
3388#ifdef TGB_DEBUG
3389        {
3390          int my_i;
3391          for (my_i=0;my_i<done_index;my_i++)
3392            pTest(done[my_i]);
3393        }
3394#endif     
3395        memmove(&(done[pos+1]),&(done[pos]), (done_index-pos)*sizeof(poly));
3396        done[pos]=m[i];
3397        done_index++;
3398#ifdef TGB_DEBUG
3399        {
3400          int my_i;
3401          for (my_i=0;my_i<done_index;my_i++)
3402          {
3403            //      Print("Position %i pos %i size %i\n",my_i,pos,done_index);
3404            pTest(done[my_i]);
3405          }
3406        }
3407#endif     
3408      }
3409      else
3410        pDelete(&m[i]);
3411#ifdef TGB_DEBUG
3412      {
3413        int my_i;
3414        for(my_i=0;my_i<done_index;my_i++)
3415        {
3416          pTest(done[my_i]);
3417          int my_j;
3418          for(my_j=0;my_j<my_i;my_j++)
3419          {
3420            assume((!pLmEqual(done[my_j],done[my_i])));
3421          }
3422        }
3423      }
3424#endif
3425    }
3426    if(p_size<p_index+q_index)
3427    {
3428      p_size=p_index+2*q_index;
3429      p=(poly*) omrealloc(p,p_size*sizeof(poly));
3430    }
3431    for (i=0;i<q_index;i++)
3432      p[p_index++]=q[i];
3433    m_index=0;
3434    int sum=0;
3435    for(i=0;i<p_index;i++)
3436    {
3437      sum+=pLength(p[i])-1;
3438    }
3439    if (m_size<sum)
3440    {
3441      omfree(m);
3442      m=(poly*) omalloc(sum*sizeof(poly));
3443    }
3444    m_size=sum;
3445    for(i=0;i<q_index;i++)
3446    {
3447      poly p_i=q[i]->next;
3448      while(p_i)
3449      {
3450        m[m_index]=pLmInit(p_i);
3451        pSetCoeff(m[m_index],nInit(1));
3452        p_i=p_i->next;
3453        m_index++;
3454      }
3455    }
3456    //qsort(done, done_index,sizeof(poly),pLmCmp_func);
3457#ifdef TGB_DEBUG
3458    for(i=0;i<done_index;i++)
3459    {
3460      pTest(done[i]);
3461    }
3462#endif
3463  }
3464#ifdef TGB_DEBUG
3465  for(i=0;i<done_index;i++)
3466  {
3467    int j;
3468    for(j=0;j<i;j++)
3469    {
3470      assume((!pLmEqual(done[j],done[i])));
3471    }
3472  }
3473#endif
3474  omfree(m);
3475  omfree(q);
3476  if (TEST_OPT_PROT)
3477    Print("Mat[%i x %i], ",chosen_index, done_index);
3478  //next Step build matrix
3479  #ifdef TGB_DEBUG
3480  for(i=0;i<done_index;i++)
3481  {
3482    int j;
3483    for(j=0;j<i;j++)
3484    {
3485      assume((!pLmEqual(done[j],done[i])));
3486    }
3487  }
3488#endif
3489  assume(p_index==chosen_index);
3490 
3491 //  tgb_matrix* mat=build_matrix(p,p_index,done, done_index,c);
3492 
3493//   simple_gauss2(mat);
3494  tgb_sparse_matrix* mat=build_sparse_matrix(p,p_index,done, done_index,c);
3495  simple_gauss(mat,c);
3496  m_size=mat->get_rows();
3497  m=(poly*) omalloc(m_size*sizeof(poly));
3498  m_index=retranslate(m,mat,done,c);
3499 
3500  mat=NULL;
3501  for(i=0;i<done_index;i++)
3502    pDelete(&done[i]);
3503  omfree(done);
3504  done=NULL;
3505  //next Step addElements to basis
3506  int F_plus_size=m_index;
3507  poly* F_plus=(poly*)omalloc(F_plus_size*sizeof(poly));
3508  int F_plus_index=0;
3509  int F_minus_size=m_index;
3510  poly* F_minus=(poly*) omalloc(F_minus_size*sizeof(poly));
3511  int F_minus_index=0;
3512
3513  //better algorithm replace p by its monoms, qsort,delete duplicates and binary search for testing if monom is contained in array
3514  qsort(p, p_index,sizeof(poly),pLmCmp_func);
3515  for(i=0;i<p_index;i++)
3516    pDelete(&p[i]->next);
3517  for(i=m_index-1;i>=0;--i)
3518  {
3519    int j;
3520    int pos=posInPolys (p,p_index, m[i],c);
3521    BOOLEAN minus=FALSE;
3522    if(((p_index>pos)&&(pLmEqual(m[i],p[pos]))) ||(pos>0) &&(pLmEqual(m[i],p[pos-1])))
3523      minus=TRUE;
3524   
3525    if(minus)
3526    {
3527      F_minus[F_minus_index++]=m[i];
3528      m[i]=NULL;
3529    }
3530    else
3531    {
3532      F_plus[F_plus_index++]=m[i];
3533      m[i]=NULL;
3534    }
3535  }
3536
3537//   for(i=m_index-1;i>=0;--i)
3538//   {
3539//     int j;
3540//     BOOLEAN minus=FALSE;
3541//     for(j=0;j<p_index;j++)
3542//       if (pLmEqual(p[j],m[i]))
3543//       {
3544//      minus=TRUE;
3545//      break;
3546//       }
3547//     if(minus)
3548//     {
3549//       F_minus[F_minus_index++]=m[i];
3550//       m[i]=NULL;
3551//     }
3552//     else
3553//     {
3554//       F_plus[F_plus_index++]=m[i];
3555//       m[i]=NULL;
3556//     }
3557//   }
3558  //in this order F_minus will be automatically ascending sorted
3559  //to make this sure for foreign gauss
3560  //uncomment the following line
3561  //  qsort(F_minus, F_minus_index,sizeof(poly),pLmCmp_func);
3562  assume((F_plus_index+F_minus_index)==m_index);
3563  if (TEST_OPT_PROT)
3564    Print("%i]", F_plus_index);
3565  for(i=0;i<p_index;i++) 
3566    pDelete(&p[i]);
3567  omfree(p);
3568  p=NULL;
3569  omfree(m);
3570  m=NULL;
3571
3572  //the F_minus list must be cleared separately at the end
3573  mp_array_list** F_i;
3574  poly_array_list** F_m_i;
3575  F_i=&(c->F);
3576  F_m_i=&(c->F_minus);
3577
3578  while((*F_i)!=NULL)
3579  {
3580    assume((*F_m_i)!=NULL);
3581    F_i=(&((*F_i)->next));
3582    F_m_i=(&((*F_m_i)->next));
3583  }
3584  assume((*F_m_i)==NULL);
3585  //should resize the array to save memory
3586  //F and F_minus
3587  qsort(chosen,chosen_index,sizeof(monom_poly),monom_poly_crit);//important for simplify
3588  (*F_m_i)=(poly_array_list*) omalloc(sizeof(poly_array_list));
3589  (*F_m_i)->size=F_minus_index;
3590  (*F_m_i)->p=F_minus;
3591  (*F_m_i)->next=NULL;
3592  (*F_i)=(mp_array_list*) omalloc(sizeof(poly_array_list));
3593  (*F_i)->size=chosen_index;
3594  (*F_i)->mp=chosen;
3595  (*F_i)->next=NULL;
3596 
3597  if(F_plus_index>0)
3598  {
3599    int j;
3600    int* ibuf=(int*) omalloc(F_plus_index*sizeof(int));
3601    sorted_pair_node*** sbuf=(sorted_pair_node***) omalloc(F_plus_index*sizeof(sorted_pair_node**));
3602 
3603    for(j=0;j<F_plus_index;j++)
3604    {
3605      int len;
3606      poly p=F_plus[j];
3607   
3608    // delete buf[j];
3609    //remember to free res here
3610    //    p=redTailShort(p, c->strat);
3611      sbuf[j]=add_to_basis_ideal_quotient(p,-1,-1,c,ibuf+j);
3612   
3613    }
3614    int sum=0;
3615    for(j=0;j<F_plus_index;j++)
3616    {
3617      sum+=ibuf[j];
3618    }
3619    sorted_pair_node** big_sbuf=(sorted_pair_node**) omalloc(sum*sizeof(sorted_pair_node*));
3620    int partsum=0;
3621    for(j=0;j<F_plus_index;j++)
3622    {
3623      memmove(big_sbuf+partsum, sbuf[j],ibuf[j]*sizeof(sorted_pair_node*));
3624      omfree(sbuf[j]);
3625      partsum+=ibuf[j];
3626    }
3627
3628    qsort(big_sbuf,sum,sizeof(sorted_pair_node*),pair_better_gen2);
3629    c->apairs=merge(c->apairs,c->pair_top+1,big_sbuf,sum,c);
3630    c->pair_top+=sum;
3631    clean_top_of_pair_list(c);
3632    omfree(big_sbuf);
3633    omfree(sbuf);
3634    omfree(ibuf);
3635  }
3636  omfree(F_plus);
3637#ifdef TGB_DEBUG
3638  int z;
3639  for(z=1;z<=c->pair_top;z++)
3640  {
3641    assume(pair_better(c->apairs[z],c->apairs[z-1],c));
3642  }
3643#endif
3644
3645  return;
3646}
3647
3648
3649static int poly_crit(const void* ap1, const void* ap2){
3650  poly p1,p2;
3651  p1=*((poly*) ap1);
3652  p2=*((poly*)ap2);
3653
3654  int c=pLmCmp(p1,p2);
3655  if (c !=0) return c;
3656  int l1=pLength(p1);
3657  int l2=pLength(p2);
3658  if (l1<l2) return -1;
3659  if (l1>l2) return 1;
3660  return 0;
3661}
3662
3663ideal t_rep_gb(ring r,ideal arg_I, BOOLEAN F4_mode){
3664  if (TEST_OPT_PROT)
3665    if (F4_mode)
3666      PrintS("F4 Modus \n");
3667   
3668     
3669  //debug_Ideal=arg_debug_Ideal;
3670  //if (debug_Ideal) PrintS("DebugIdeal received\n");
3671  // Print("Idelems %i \n----------\n",IDELEMS(arg_I));
3672  ideal I=idCompactify(arg_I);
3673  qsort(I->m,IDELEMS(I),sizeof(poly),poly_crit);
3674  //Print("Idelems %i \n----------\n",IDELEMS(I));
3675  calc_dat* c=(calc_dat*) omalloc(sizeof(calc_dat));
3676 
3677  c->r=currRing;
3678  c->is_homog=TRUE;
3679  {
3680    int hz;
3681    for(hz=0;hz<IDELEMS(I);hz++){
3682      assume(I->m[hz]!=NULL);
3683      int d=pTotaldegree(I->m[hz]);
3684      poly t=I->m[hz]->next;
3685      while(t)
3686      {
3687        if (d!=pTotaldegree(t,c->r))
3688        {
3689          c->is_homog=FALSE;
3690          break;
3691        }
3692        t=t->next;
3693      }
3694      if(!(c->is_homog)) break;
3695    }
3696  }
3697  //  Print("is homog:%d",c->is_homog);
3698  void* h;
3699  poly hp;
3700  int i,j;
3701  c->to_destroy=NULL;
3702  c->easy_product_crit=0;
3703  c->extended_product_crit=0;
3704  c->is_char0=(rChar()==0);
3705  c->F4_mode=F4_mode;
3706  c->reduction_steps=0;
3707  c->last_index=-1;
3708
3709  c->F=NULL;
3710  c->F_minus=NULL;
3711
3712  c->Rcounter=0;
3713
3714  c->soon_free=NULL;
3715
3716  c->tmp_lm=pOne();
3717
3718  c->normal_forms=0;
3719  c->current_degree=1;
3720 
3721  c->max_pairs=5*I->idelems();
3722 
3723  c->apairs=(sorted_pair_node**) omalloc(sizeof(sorted_pair_node*)*c->max_pairs);
3724  c->pair_top=-1;
3725
3726  int n=I->idelems();
3727  if (TEST_OPT_PROT)
3728    for (i=0;i<n;i++){
3729      wrp(I->m[i]);
3730      PrintS("\n");
3731    }
3732  i=0;
3733  c->n=0;
3734  c->T_deg=(int*) omalloc(n*sizeof(int));
3735  c->tmp_pair_lm=(poly*) omalloc(n*sizeof(poly));
3736  lm_bin=omGetSpecBin(POLYSIZE + (r->ExpL_Size)*sizeof(long));
3737#ifdef HEAD_BIN
3738  c->HeadBin=omGetSpecBin(POLYSIZE + (currRing->ExpL_Size)*sizeof(long));
3739#endif
3740  /* omUnGetSpecBin(&(c->HeadBin)); */
3741  h=omalloc(n*sizeof(char*));
3742  c->states=(char**) h;
3743  h=omalloc(n*sizeof(int));
3744  c->lengths=(int*) h;
3745  h=omalloc(n*sizeof(int));
3746        c->gcd_of_terms=(poly*) omalloc(n*sizeof(poly));
3747  c->rep=(int*) h;
3748  c->short_Exps=(long*) omalloc(n*sizeof(long));
3749  c->S=idInit(n,1);
3750  c->strat=new skStrategy;
3751  c->strat->syzComp = 0;
3752  initBuchMoraCrit(c->strat);
3753  initBuchMoraPos(c->strat);
3754  c->strat->initEcart = initEcartBBA;
3755  c->strat->enterS = enterSBba;
3756  c->strat->sl = -1;
3757  i=n;
3758  /* initS(c->S,NULL,c->strat); */
3759/* intS start: */
3760  i=((i+IDELEMS(c->S)+15)/16)*16;
3761  c->strat->ecartS=(intset)omAlloc(i*sizeof(int)); /*initec(i);*/
3762  c->strat->sevS=(unsigned long*)omAlloc0(i*sizeof(unsigned long));
3763  /*initsevS(i);*/
3764  c->strat->S_2_R=(int*)omAlloc0(i*sizeof(int));/*initS_2_R(i);*/
3765  c->strat->fromQ=NULL;
3766  c->strat->Shdl=idInit(1,1);
3767  c->strat->S=c->strat->Shdl->m;
3768  c->strat->lenS=(int*)omAlloc0(i*sizeof(int));
3769  if(c->is_char0)
3770    c->strat->lenSw=(int*)omAlloc0(i*sizeof(int));
3771  else
3772    c->strat->lenSw=NULL;
3773  sorted_pair_node* si;
3774  assume(n>0);
3775  add_to_basis(I->m[0],-1,-1,c);
3776
3777  assume(c->strat->sl==c->strat->Shdl->idelems()-1);
3778  if(!(F4_mode))
3779  {
3780    for (i=1;i<n;i++)//the 1 is wanted, because first element is added to basis
3781    {
3782      //     add_to_basis(I->m[i],-1,-1,c);
3783      si=(sorted_pair_node*) omalloc(sizeof(sorted_pair_node));
3784      si->i=-1;
3785      si->j=-1;
3786      si->expected_length=pLength(I->m[i]);
3787      si->deg=pTotaldegree(I->m[i]);
3788      if (!rField_is_Zp(c->r)){ 
3789        pCleardenom(I->m[i]);
3790      }
3791      si->lcm_of_lm=I->m[i];
3792     
3793      //      c->apairs[n-1-i]=si;
3794      c->apairs[n-i-1]=si;
3795      ++(c->pair_top);
3796    }
3797  }
3798  else
3799  {
3800     for (i=1;i<n;i++)//the 1 is wanted, because first element is added to basis
3801       add_to_basis(I->m[i],-1,-1,c);
3802  }
3803   
3804
3805  while(c->pair_top>=0)
3806  {
3807    if(F4_mode)
3808      go_on_F4(c);
3809    else
3810      go_on(c);
3811  }
3812  while(c->to_destroy)
3813  {
3814    pDelete(&(c->to_destroy->p));
3815    poly_list_node* old=c->to_destroy;
3816    c->to_destroy=c->to_destroy->next;
3817    omfree(old);
3818  }
3819  while(c->F)
3820  {
3821    for(i=0;i<c->F->size;i++){
3822      pDelete(&(c->F->mp[i].m));
3823    }
3824    omfree(c->F->mp);
3825    c->F->mp=NULL;
3826    mp_array_list* old=c->F;
3827    c->F=c->F->next;
3828    omfree(old);
3829  }
3830  while(c->F_minus)
3831  {
3832    for(i=0;i<c->F_minus->size;i++){
3833      pDelete(&(c->F_minus->p[i]));
3834    }
3835    omfree(c->F_minus->p);
3836    c->F_minus->p=NULL;
3837    poly_array_list* old=c->F_minus;
3838    c->F_minus=c->F_minus->next;
3839    omfree(old);
3840  }
3841  for(int z=0;z<c->n;z++){
3842    omfree(c->states[z]);
3843  }
3844  omfree(c->states);
3845  omfree(c->lengths);
3846  for(int z=0;z<c->n;z++)
3847  {
3848    pDelete(&c->tmp_pair_lm[z]);
3849  }
3850  omfree(c->tmp_pair_lm);
3851
3852  omfree(c->short_Exps);
3853  omfree(c->T_deg);
3854
3855     omFree(c->strat->ecartS);
3856     omFree(c->strat->sevS);
3857//   initsevS(i);
3858   omFree(c->strat->S_2_R);
3859   
3860
3861  omFree(c->strat->lenS);
3862
3863   if(c->strat->lenSw)  omFree(c->strat->lenSw);
3864
3865
3866
3867
3868  for(i=0;i<c->n;i++){
3869    if(c->gcd_of_terms[i])
3870      pDelete(&(c->gcd_of_terms[i]));
3871  }
3872  omfree(c->gcd_of_terms);
3873
3874  omfree(c->apairs);
3875  if (TEST_OPT_PROT)
3876  {
3877    Print("calculated %d NFs\n",c->normal_forms);
3878    Print("applied %i product crit, %i extended_product crit \n", c->easy_product_crit, c->extended_product_crit);
3879  }
3880  int deleted_form_c_s=0;
3881 
3882  for(i=0;i<=c->strat->sl;i++){
3883    if (!c->strat->S[i]) continue;
3884    BOOLEAN found=FALSE;
3885    for(j=0;j<c->n;j++){
3886      if (c->S->m[j]==c->strat->S[i]){
3887        found=TRUE;
3888        break;
3889      }
3890    }
3891    if(!found) pDelete(&c->strat->S[i]);
3892  }
3893//   for(i=0;i<c->n;i++){
3894//     if (c->rep[i]!=i){
3895// //       for(j=0;j<=c->strat->sl;j++){
3896// //   if(c->strat->S[j]==c->S->m[i]){
3897// //     c->strat->S[j]=NULL;
3898// //     break;
3899// //   }
3900// //       }
3901// //      PrintS("R_delete");
3902//       pDelete(&c->S->m[i]);
3903//     }
3904//   }
3905
3906//  qsort(c->S->m, c->n,sizeof(poly),pLmCmp_func);
3907  for(i=0;i<c->n;i++)
3908  {
3909    assume(c->S->m[i]!=NULL);
3910    for(j=0;j<c->n;j++)
3911    {
3912      if((c->S->m[j]==NULL)||(i==j)) 
3913        continue;
3914      assume(p_LmShortDivisibleBy(c->S->m[j],c->short_Exps[j],
3915                               c->S->m[i],~c->short_Exps[i],
3916                                   c->r)==p_LmDivisibleBy(c->S->m[j],
3917                                                        c->S->m[i],
3918                                                          c->r));
3919      if (p_LmShortDivisibleBy(c->S->m[j],c->short_Exps[j],
3920                               c->S->m[i],~c->short_Exps[i],
3921                                   c->r))
3922      {
3923        pDelete(&c->S->m[i]);
3924        break;
3925      }
3926    }
3927  }
3928  omfree(c->rep);
3929  for(i=0;i<I->idelems();i++)
3930  {
3931    I->m[i]=NULL;
3932  }
3933  idDelete(&I);
3934  I=c->S;
3935 
3936  IDELEMS(I)=c->n;
3937
3938  idSkipZeroes(c->S);
3939  for(i=0;i<=c->strat->sl;i++)
3940    c->strat->S[i]=NULL;
3941  id_Delete(&c->strat->Shdl,c->r);
3942  pDelete(&c->tmp_lm);
3943  omUnGetSpecBin(&lm_bin);
3944  delete c->strat;
3945  omfree(c);
3946
3947  return(I);
3948}
3949static void now_t_rep(const int & arg_i, const int & arg_j, calc_dat* c){
3950  int i,j;
3951  if (arg_i==arg_j){
3952    return;
3953  }
3954  if (arg_i>arg_j){
3955    i=arg_j;
3956    j=arg_i;
3957  } else {
3958    i=arg_i;
3959    j=arg_j;
3960  }
3961  c->states[j][i]=HASTREP;
3962}
3963static void soon_t_rep(const int& arg_i, const int& arg_j, calc_dat* c)
3964{
3965  assume(0<=arg_i);
3966  assume(0<=arg_j);
3967  assume(arg_i<c->n);
3968  assume(arg_j<c->n);
3969  int i,j;
3970  if (arg_i==arg_j){
3971    return;
3972  }
3973  if (arg_i>arg_j){
3974    i=arg_j;
3975    j=arg_i;
3976  } else {
3977    i=arg_i;
3978    j=arg_j;
3979  }
3980  if (!
3981      (c->states[j][i]==HASTREP))
3982    c->states[j][i]=SOONTREP;
3983}
3984static BOOLEAN has_t_rep(const int & arg_i, const  int & arg_j, calc_dat* state){
3985  assume(0<=arg_i);
3986  assume(0<=arg_j);
3987  assume(arg_i<state->n);
3988  assume(arg_j<state->n);
3989  if (arg_i==arg_j)
3990  {
3991    return (TRUE);
3992  }
3993  if (arg_i>arg_j)
3994  {
3995    return (state->states[arg_i][arg_j]==HASTREP);
3996  } else
3997  {
3998    return (state->states[arg_j][arg_i]==HASTREP);
3999  }
4000}
4001static int pLcmDeg(poly a, poly b)
4002{
4003  int i;
4004  int n=0;
4005  for (i=pVariables; i; i--)
4006  {
4007    n+=max( pGetExp(a,i), pGetExp(b,i));
4008  }
4009  return n;
4010
4011}
4012
4013
4014
4015static void shorten_tails(calc_dat* c, poly monom)
4016{
4017  return;
4018// BOOLEAN corr=lenS_correct(c->strat);
4019  for(int i=0;i<c->n;i++)
4020  {
4021    //enter tail
4022    if (c->rep[i]!=i) continue;
4023    if (c->S->m[i]==NULL) continue;
4024    poly tail=c->S->m[i]->next;
4025    poly prev=c->S->m[i];
4026    BOOLEAN did_something=FALSE;
4027    while((tail!=NULL)&& (pLmCmp(tail, monom)>=0))
4028    {
4029      if (p_LmDivisibleBy(monom,tail,c->r))
4030      {
4031        did_something=TRUE;
4032        prev->next=tail->next;
4033        tail->next=NULL;
4034        p_Delete(& tail,c->r);
4035        tail=prev;
4036        //PrintS("Shortened");
4037        c->lengths[i]--;
4038      }
4039      prev=tail;
4040      tail=tail->next;
4041    }
4042    if (did_something)
4043    {
4044      int new_pos;
4045      int q;
4046      q=quality(c->S->m[i],c->lengths[i],c);
4047      new_pos=simple_posInS(c->strat,c->S->m[i],q,c->is_char0);
4048
4049      int old_pos=-1;
4050      //assume new_pos<old_pos
4051      for (int z=0;z<=c->strat->sl;z++)
4052      {
4053        if (c->strat->S[z]==c->S->m[i])
4054        {
4055          old_pos=z;
4056          break;
4057        }
4058      }
4059      if (old_pos== -1)
4060        for (int z=new_pos-1;z>=0;z--)
4061        {
4062          if (c->strat->S[z]==c->S->m[i])
4063          {
4064            old_pos=z;
4065            break;
4066          }
4067        }
4068      assume(old_pos>=0);
4069      assume(new_pos<=old_pos);
4070      assume(pLength(c->strat->S[old_pos])==c->lengths[i]);
4071      c->strat->lenS[old_pos]=c->lengths[i];
4072      if (c->strat->lenSw)
4073        c->strat->lenSw[old_pos]=q;
4074
4075      if (new_pos<old_pos)
4076        move_forward_in_S(old_pos,new_pos,c->strat, c->is_char0);
4077
4078      length_one_crit(c,i,c->lengths[i]);
4079    }
4080  }
4081}
4082static sorted_pair_node* pop_pair(calc_dat* c){
4083  clean_top_of_pair_list(c);
4084
4085  if(c->pair_top<0) return NULL;
4086  else return (c->apairs[c->pair_top--]);
4087}
4088static sorted_pair_node* top_pair(calc_dat* c){
4089  super_clean_top_of_pair_list(c);//yeah, I know, it's odd that I use a different proc here
4090
4091  if(c->pair_top<0) return NULL;
4092  else return (c->apairs[c->pair_top]);
4093}
4094static sorted_pair_node* quick_pop_pair(calc_dat* c){
4095  if(c->pair_top<0) return NULL;
4096  else return (c->apairs[c->pair_top--]);
4097}
4098static BOOLEAN no_pairs(calc_dat* c){
4099  clean_top_of_pair_list(c);
4100  return (c->pair_top==-1);
4101}
4102
4103
4104static void super_clean_top_of_pair_list(calc_dat* c){
4105  while((c->pair_top>=0)
4106  && (c->apairs[c->pair_top]->i>=0)
4107  && (good_has_t_rep(c->apairs[c->pair_top]->j, c->apairs[c->pair_top]->i,c)))
4108  {
4109
4110    free_sorted_pair_node(c->apairs[c->pair_top],c->r);
4111    c->pair_top--;
4112
4113  }
4114}
4115static void clean_top_of_pair_list(calc_dat* c){
4116  while((c->pair_top>=0) && (c->apairs[c->pair_top]->i>=0) && (!state_is(UNCALCULATED,c->apairs[c->pair_top]->j, c->apairs[c->pair_top]->i,c))){
4117
4118    free_sorted_pair_node(c->apairs[c->pair_top],c->r);
4119    c->pair_top--;
4120
4121  }
4122}
4123static BOOLEAN state_is(calc_state state, const int & arg_i, const  int & arg_j, calc_dat* c){
4124  assume(0<=arg_i);
4125  assume(0<=arg_j);
4126  assume(arg_i<c->n);
4127  assume(arg_j<c->n);
4128  if (arg_i==arg_j)
4129  {
4130    return (TRUE);
4131  }
4132  if (arg_i>arg_j)
4133  {
4134    return (c->states[arg_i][arg_j]==state);
4135  }
4136  else return(c->states[arg_j][arg_i]==state);
4137}
4138static void free_sorted_pair_node(sorted_pair_node* s, ring r){
4139  if (s->i>=0)
4140    p_Delete(&s->lcm_of_lm,r);
4141  omfree(s);
4142}
4143static BOOLEAN pair_better(sorted_pair_node* a,sorted_pair_node* b, calc_dat* c){
4144  if (a->deg<b->deg) return TRUE;
4145  if (a->deg>b->deg) return FALSE;
4146
4147//  if (a->expected_length<b->expected_length) return TRUE;
4148  //  if (a->expected_length>b->expected_length) return FALSE;
4149  int comp=pLmCmp(a->lcm_of_lm, b->lcm_of_lm);
4150  if (comp==1) return FALSE;
4151  if (-1==comp) return TRUE;
4152  if (a->i+a->j<b->i+b->j) return TRUE;
4153   if (a->i+a->j>b->i+b->j) return FALSE;
4154  if (a->i<b->i) return TRUE;
4155  if (a->i>b->i) return FALSE;
4156  return TRUE;
4157}
4158
4159static int pair_better_gen(const void* ap,const void* bp){
4160
4161  sorted_pair_node* a=*((sorted_pair_node**)ap);
4162  sorted_pair_node* b=*((sorted_pair_node**)bp);
4163  assume(a->i>a->j);
4164  assume(b->i>b->j);
4165  if (a->deg<b->deg) return -1;
4166  if (a->deg>b->deg) return 1;
4167
4168
4169//  if (a->expected_length<b->expected_length) return -1;
4170  // if (a->expected_length>b->expected_length) return 1;
4171 int comp=pLmCmp(a->lcm_of_lm, b->lcm_of_lm);
4172 
4173  if (comp==1) return 1;
4174  if (-1==comp) return -1;
4175  if (a->i+a->j<b->i+b->j) return -1;
4176   if (a->i+a->j>b->i+b->j) return 1;
4177  if (a->i<b->i) return -1;
4178   if (a->i>b->i) return 1;
4179  return 0;
4180}
4181
4182
4183static poly gcd_of_terms(poly p, ring r){
4184  int max_g_0=0;
4185  assume(p!=NULL);
4186  int i;
4187  poly m=pOne();
4188  poly t;
4189  for (i=pVariables; i; i--)
4190  {
4191      pSetExp(m,i, pGetExp(p,i));
4192      if (max_g_0==0)
4193        if (pGetExp(m,i)>0)
4194          max_g_0=i;
4195  }
4196 
4197  t=p->next;
4198  while (t!=NULL){
4199   
4200    if (max_g_0==0) break;
4201    for (i=max_g_0; i; i--)
4202    {
4203      pSetExp(m,i, min(pGetExp(t,i),pGetExp(m,i)));
4204      if (max_g_0==i)
4205        if (pGetExp(m,i)==0)
4206          max_g_0=0;
4207      if ((max_g_0==0) && (pGetExp(m,i)>0)){
4208        max_g_0=i;
4209      }
4210    }
4211    t=t->next;
4212  }
4213  // for (i=pVariables;i;i--)
4214//   {
4215//     if(pGetExp(m,i)>0)
4216//       return m;
4217//   }
4218  if (max_g_0>0)
4219    return m;
4220  pDelete(&m);
4221  return NULL;
4222}
4223static inline BOOLEAN pHasNotCFExtended(poly p1, poly p2, poly m)
4224{
4225
4226  if (pGetComp(p1) > 0 || pGetComp(p2) > 0)
4227    return FALSE;
4228  int i = 1;
4229  loop
4230  {
4231    if ((pGetExp(p1, i)-pGetExp(m,i) >0) && (pGetExp(p2, i) -pGetExp(m,i)> 0))   return FALSE;
4232    if (i == pVariables)                                return TRUE;
4233    i++;
4234  }
4235}
4236
4237
4238//for impl reasons may return false if the the normal product criterion matches
4239static inline BOOLEAN extended_product_criterion(poly p1, poly gcd1, poly p2, poly gcd2, calc_dat* c){
4240  if(gcd1==NULL) return FALSE;
4241        if(gcd2==NULL) return FALSE;
4242        gcd1->next=gcd2; //may ordered incorrect
4243        poly m=gcd_of_terms(gcd1,c->r);
4244        gcd1->next=NULL;
4245        if (m==NULL) return FALSE;
4246
4247        BOOLEAN erg=pHasNotCFExtended(p1,p2,m);
4248        pDelete(&m);
4249        return erg;
4250}
4251static poly kBucketGcd(kBucket* b, ring r)
4252{
4253  int s=0;
4254  int i;
4255  poly m, n;
4256  BOOLEAN initialized=FALSE;
4257  for (i=MAX_BUCKET-1;i>=0;i--)
4258  { 
4259    if (b->buckets[i]!=NULL){
4260      if (!initialized){
4261        m=gcd_of_terms(b->buckets[i],r);
4262        initialized=TRUE;
4263        if (m==NULL) return NULL;
4264      }
4265      else
4266        {
4267          n=gcd_of_terms(b->buckets[i],r);
4268          if (n==NULL) {
4269            pDelete(&m);
4270            return NULL;   
4271          }
4272          n->next=m;
4273          poly t=gcd_of_terms(n,r);
4274          n->next=NULL;
4275          pDelete(&m);
4276          pDelete(&n);
4277          m=t;
4278          if (m==NULL) return NULL;
4279         
4280        }
4281    }
4282  }
4283  return m;
4284}
4285
4286
4287
4288static int guess_quality(const red_object & p, calc_dat* c){
4289  //looks only on bucket
4290  if (c->is_char0) return kSBucketLength(p.bucket);
4291  return (bucket_guess(p.bucket));
4292}
4293static int quality_of_pos_in_strat_S(int pos, calc_dat* c){
4294  if (c->is_char0) return c->strat->lenSw[pos];
4295  return c->strat->lenS[pos];
4296}
4297static int quality(poly p, int len, calc_dat* c){
4298  if (c->is_char0) return pSLength(p,len);
4299  return pLength(p);
4300}
4301static void multi_reduction_lls_trick(red_object* los, int losl,calc_dat* c,find_erg & erg){
4302  erg.expand=NULL;
4303  BOOLEAN swap_roles; //from reduce_by, to_reduce_u if fromS
4304  if(erg.fromS){
4305    if(pLmEqual(c->strat->S[erg.reduce_by],los[erg.to_reduce_u].p))
4306    {
4307      int i;
4308      int quality_a=quality_of_pos_in_strat_S(erg.reduce_by,c);
4309      int best=erg.to_reduce_u+1;
4310/*
4311      for (i=erg.to_reduce_u;i>=erg.to_reduce_l;i--){
4312        int qc=los[i].guess_quality(c);
4313        if (qc<quality_a){
4314          best=i;
4315          quality_a=qc;
4316        }
4317      }
4318      if(best!=erg.to_reduce_u+1){*/
4319      int qc;
4320      best=find_best(los,erg.to_reduce_l,erg.to_reduce_u,qc,c);
4321      assume(qc==los[best].guess_quality(c));
4322      if(qc<quality_a){
4323        red_object h=los[erg.to_reduce_u];
4324        los[erg.to_reduce_u]=los[best];
4325        los[best]=h;
4326        swap_roles=TRUE;
4327      }
4328      else{
4329       
4330        swap_roles=FALSE;
4331      }
4332 
4333    }
4334      else
4335    {
4336      if (erg.to_reduce_u>erg.to_reduce_l){
4337
4338        int i;
4339        int quality_a=quality_of_pos_in_strat_S(erg.reduce_by,c);
4340        int best=erg.to_reduce_u+1;
4341        int qc;
4342        best=find_best(los,erg.to_reduce_l,erg.to_reduce_u,qc,c);
4343        assume(qc==los[best].guess_quality(c));
4344        if(qc<quality_a){
4345          //(best!=erg.to_reduce_u+1){
4346          red_object h=los[erg.to_reduce_l];
4347          los[erg.to_reduce_l]=los[best];
4348          los[best]=h;
4349          erg.reduce_by=erg.to_reduce_l;
4350          erg.fromS=FALSE;
4351          erg.to_reduce_l++;
4352         
4353        }
4354      }
4355      else 
4356      {
4357        assume(erg.to_reduce_u==erg.to_reduce_l);
4358        int quality_a=quality_of_pos_in_strat_S(erg.reduce_by,c);
4359        int qc=los[erg.to_reduce_u].guess_quality(c);
4360        if(qc<quality_a){
4361          BOOLEAN exp=FALSE;
4362          if(qc<=2)
4363            exp=TRUE;
4364          else {
4365            if (qc<quality_a/2)
4366              exp=TRUE;
4367            else
4368              if(erg.reduce_by<c->n/4)
4369                exp=TRUE;
4370          }
4371          if (exp){
4372            poly clear_into;
4373            los[erg.to_reduce_u].flatten();
4374            kBucketClear(los[erg.to_reduce_u].bucket,&clear_into,&erg.expand_length);
4375            erg.expand=pCopy(clear_into);
4376            kBucketInit(los[erg.to_reduce_u].bucket,clear_into,erg.expand_length);
4377            if (TEST_OPT_PROT)
4378              PrintS("e");
4379           
4380          }
4381        }
4382
4383       
4384      }
4385     
4386      swap_roles=FALSE;
4387      return;
4388      }
4389   
4390  }
4391  else{
4392    if(erg.reduce_by>erg.to_reduce_u){
4393      //then lm(rb)>= lm(tru) so =
4394      assume(erg.reduce_by==erg.to_reduce_u+1);
4395      int best=erg.reduce_by;
4396      int quality_a=los[erg.reduce_by].guess_quality(c);
4397      int qc;
4398      best=find_best(los,erg.to_reduce_l,erg.to_reduce_u,qc,c);
4399     
4400      int i;
4401      if(qc<quality_a){
4402          red_object h=los[erg.reduce_by];
4403          los[erg.reduce_by]=los[best];
4404          los[best]=h;
4405        }
4406        swap_roles=FALSE;
4407        return;
4408       
4409         
4410    }
4411    else
4412    {
4413      assume(!pLmEqual(los[erg.reduce_by].p,los[erg.to_reduce_l].p));
4414      //further assume, that reduce_by is the above all other polys
4415      //with same leading term
4416      int il=erg.reduce_by;
4417      int quality_a =los[erg.reduce_by].guess_quality(c);
4418      int qc;
4419      while((il>0) && pLmEqual(los[il-1].p,los[il].p)){
4420        il--;
4421        qc=los[il].guess_quality(c);
4422        if (qc<quality_a){
4423          quality_a=qc;
4424          erg.reduce_by=il;
4425        }
4426      }
4427      swap_roles=FALSE;
4428    }
4429 
4430  }
4431  if(swap_roles)
4432  {
4433    if (TEST_OPT_PROT)
4434      PrintS("b");
4435    poly clear_into;
4436    int dummy_len;
4437    int new_length;
4438    int bp=erg.to_reduce_u;//bucket_positon
4439    //kBucketClear(los[bp].bucket,&clear_into,&new_length);
4440    new_length=los[bp].clear_to_poly();
4441    clear_into=los[bp].p;
4442    poly p=c->strat->S[erg.reduce_by];
4443    int j=erg.reduce_by;
4444    int old_length=c->strat->lenS[j];// in view of S
4445    los[bp].p=p;
4446    kBucketInit(los[bp].bucket,p,old_length);
4447    int qal=quality(clear_into,new_length,c);
4448    int pos_in_c=-1;   
4449    int z;
4450    int new_pos;
4451    new_pos=simple_posInS(c->strat,clear_into,qal,c->is_char0);
4452    assume(new_pos<=j);
4453    for (z=c->n;z;z--)
4454    {
4455      if(p==c->S->m[z-1])
4456      {
4457        pos_in_c=z-1;
4458        break;
4459      }
4460    }
4461    if(pos_in_c>=0)
4462    {
4463      c->S->m[pos_in_c]=clear_into;
4464      c->lengths[pos_in_c]=new_length;
4465      c_S_element_changed_hook(pos_in_c,c);
4466    }
4467    c->strat->S[j]=clear_into;
4468    c->strat->lenS[j]=new_length;
4469    if(c->strat->lenSw)
4470      c->strat->lenS[j]=qal;
4471    if (!rField_is_Zp(c->r))
4472    {
4473      pContent(clear_into);
4474      pCleardenom(clear_into);//should be unnecessary
4475    }
4476    else                     
4477      pNorm(clear_into);
4478#ifdef FIND_DETERMINISTIC
4479    erg.reduce_by=j;
4480    //resort later see diploma thesis, find_in_S must be deterministic
4481    //during multireduction if spolys are only in the span of the
4482    //input polys
4483#else
4484   
4485    if (new_pos<j)
4486    { 
4487      move_forward_in_S(j,new_pos,c->strat,c->is_char0);
4488      erg.reduce_by=new_pos;
4489    }
4490#endif
4491  }
4492}
4493static int fwbw(red_object* los, int i){
4494   int i2=i;
4495   int step=1;
4496   
4497   BOOLEAN bw=FALSE;
4498   BOOLEAN incr=TRUE;
4499   
4500   while(1)
4501   {
4502     if(!bw)
4503     {
4504       step=min(i2,step);
4505       if (step==0) break;
4506       i2-=step;
4507         
4508       if(!pLmEqual(los[i].p,los[i2].p))
4509       {
4510         bw=TRUE;
4511         incr=FALSE;
4512       }
4513       else
4514       {
4515         if ((!incr) &&(step==1)) break;
4516       }
4517       
4518       
4519     }
4520     else
4521     {
4522       
4523       step=min(i-i2,step);
4524       if (step==0) break;
4525       i2+=step;
4526       if(pLmEqual(los[i].p,los[i2].p)){
4527         if(step==1) break;
4528         else
4529         {
4530           bw=FALSE;
4531         }
4532       }
4533       
4534     }
4535     if (incr)
4536       step*=2;
4537     else
4538     {
4539       if (step%2==1)
4540         step=(step+1)/2;
4541       else
4542         step/=2;
4543       
4544     }
4545   }
4546   return i2;
4547}
4548static void multi_reduction_find(red_object* los, int losl,calc_dat* c,int startf,find_erg & erg){
4549  kStrategy strat=c->strat;
4550
4551  assume(startf<=losl);
4552  assume((startf==losl-1)||(pLmCmp(los[startf].p,los[startf+1].p)==-1));
4553  int i=startf;
4554 
4555  int j;
4556  while(i>=0){
4557    assume((i==losl-1)||(pLmCmp(los[i].p,los[i+1].p)<=0));
4558    assume(is_valid_ro(los[i]));
4559    j=kFindDivisibleByInS_easy(strat,los[i]);
4560    if(j>=0){
4561     
4562      erg.to_reduce_u=i;
4563      erg.reduce_by=j;
4564      erg.fromS=TRUE;
4565      int i2=fwbw(los,i);
4566      assume(pLmEqual(los[i].p,los[i2].p));
4567      assume((i2==0)||(!pLmEqual(los[i2].p,los[i2-1].p)));
4568      assume(i>=i2);
4569
4570//       int i2;
4571//       for(i2=i-1;i2>=0;i2--){
4572//      if(!pLmEqual(los[i].p,los[i2].p))
4573//        break;
4574//      }
4575     
4576//      erg.to_reduce_l=i2+1;
4577      erg.to_reduce_l=i2;
4578      assume((i==losl-1)||(pLmCmp(los[i].p,los[i+1].p)==-1));
4579      return;
4580    }
4581    if (j<0){
4582     
4583      //not reduceable, try to use this for reducing higher terms
4584      int i2=fwbw(los,i);
4585      assume(pLmEqual(los[i].p,los[i2].p));
4586      assume((i2==0)||(!pLmEqual(los[i2].p,los[i2-1].p)));
4587      assume(i>=i2);
4588      if(i2!=i){
4589       
4590        erg.to_reduce_u=i-1;
4591        erg.to_reduce_l=i2;
4592        erg.reduce_by=i;
4593        erg.fromS=FALSE;
4594        assume((i==losl-1)||(pLmCmp(los[i].p,los[i+1].p)==-1));
4595        return;
4596      }
4597      if(!(c->is_homog))
4598      {
4599
4600        for (i2=i+1;i2<losl;i2++){
4601          if (p_LmShortDivisibleBy(los[i].p,los[i].sev,los[i2].p,~los[i2].sev,
4602                                   c->r)){
4603            int i3=i2;
4604            while((i3+1<losl) && (pLmEqual(los[i2].p, los[i3+1].p)))
4605              i3++;
4606            erg.to_reduce_u=i3;
4607            erg.to_reduce_l=i2;
4608            erg.reduce_by=i;
4609            erg.fromS=FALSE;
4610            assume((i==losl-1)||(pLmCmp(los[i].p,los[i+1].p)==-1));
4611            return;
4612          }
4613          //    else {assume(!p_LmDivisibleBy(los[i].p, los[i2].p,c->r));}
4614        }
4615      }
4616      i--;
4617    }
4618  }
4619  erg.reduce_by=-1;//error code
4620  return;
4621}
4622
4623 //  nicht reduzierbare eintraege in ergebnisliste schreiben
4624//   nullen loeschen
4625//   while(finde_groessten leitterm reduzierbar(c,erg)){
4626 
4627static int multi_reduction_clear_zeroes(red_object* los, int  losl, int l, int u)
4628{
4629
4630
4631  int deleted=0;
4632  int  i=l;
4633  int last=-1;
4634  while(i<=u)
4635  {
4636   
4637    if(los[i].p==NULL){
4638      kBucketDestroy(&los[i].bucket);
4639//      delete los[i];//here we assume los are constructed with new
4640      //destroy resources, must be added here   
4641     if (last>=0)
4642     {
4643       memmove(los+(int)(last+1-deleted),los+(last+1),sizeof(red_object)*(i-1-last));
4644     }
4645     last=i;
4646     deleted++;
4647    }
4648    i++;
4649  }
4650  if((last>=0)&&(last!=losl-1))
4651      memmove(los+(int)(last+1-deleted),los+last+1,sizeof(red_object)*(losl-1-last));
4652  return deleted;
4653 
4654}
4655
4656static void sort_region_down(red_object* los, int l, int u, calc_dat* c)
4657{
4658  qsort(los+l,u-l+1,sizeof(red_object),red_object_better_gen);
4659  int i;
4660
4661  for(i=l;i<=u;i++)
4662  {
4663    BOOLEAN moved=FALSE;
4664    int j;
4665    for(j=i;j;j--)
4666    {
4667      if(pLmCmp(los[j].p,los[j-1].p)==-1){
4668        red_object h=los[j];
4669        los[j]=los[j-1];
4670        los[j-1]=h;
4671        moved=TRUE;
4672      }
4673      else break;
4674    }
4675    if(!moved) return;
4676  }
4677}
4678
4679//assume that los is ordered ascending by leading term, all non zero
4680static void multi_reduction(red_object* los, int & losl, calc_dat* c)
4681{
4682 
4683  //initialize;
4684  assume(c->strat->sl>=0);
4685  assume(losl>0);
4686  int i;
4687  for(i=0;i<losl;i++){
4688    los[i].sev=pGetShortExpVector(los[i].p);
4689//SetShortExpVector();
4690    los[i].p=kBucketGetLm(los[i].bucket);
4691  }
4692
4693  kStrategy strat=c->strat;
4694  int curr_pos=losl-1;
4695
4696
4697//  nicht reduzierbare einträge in ergebnisliste schreiben
4698  // nullen loeschen
4699  while(curr_pos>=0){
4700   
4701    find_erg erg;
4702    multi_reduction_find(los, losl,c,curr_pos,erg);//last argument should be curr_pos
4703   //  PrintS("\n erg:\n");
4704//     Print("upper:%i\n",erg.to_reduce_u);
4705//     Print("lower:%i\n",erg.to_reduce_l);
4706//     Print("reduce_by:%i\n",erg.reduce_by);
4707//     Print("fromS:%i\n",erg.fromS);
4708    if(erg.reduce_by<0) break;
4709
4710
4711
4712    erg.expand=NULL;
4713    int d=erg.to_reduce_u-erg.to_reduce_l+1;
4714    //if ((!erg.fromS)&&(d>100)){
4715    if (0){
4716      PrintS("L");
4717      if(!erg.fromS){
4718        erg.to_reduce_u=max(erg.to_reduce_u,erg.reduce_by);
4719        if (pLmEqual(los[erg.reduce_by].p,los[erg.to_reduce_l].p))
4720          erg.to_reduce_l=min(erg.to_reduce_l,erg.reduce_by);
4721      }
4722      int pn=erg.to_reduce_u+1-erg.to_reduce_l;
4723      poly* p=(poly*) omalloc((pn)*sizeof(poly));
4724      int i;
4725      for(i=0;i<pn;i++){
4726        int len;
4727        los[erg.to_reduce_l+i].flatten();
4728        kBucketClear(los[erg.to_reduce_l+i].bucket,&p[i],&len);
4729       
4730        redTailShort(p[i],c->strat);
4731      }
4732      pre_comp(p,pn,c);
4733      int j;
4734      for(j=0;j<pn;j++){
4735        los[erg.to_reduce_l+j].p=p[j];
4736        los[erg.to_reduce_l+j].sev=pGetShortExpVector(p[j]);
4737        los[erg.to_reduce_l+j].sum=NULL;
4738        int len=pLength(p[j]);
4739        kBucketInit(los[erg.to_reduce_l+j].bucket,los[erg.to_reduce_l+j].p,len);
4740      }
4741      for(j=erg.to_reduce_l+pn;j<=erg.to_reduce_u;j++){
4742        los[j].p=NULL;
4743       
4744      }
4745
4746      omfree(p);
4747    }
4748    else {
4749    multi_reduction_lls_trick(los,losl,c,erg);
4750    int sum=0;
4751
4752   
4753    int i;
4754    int len;
4755   
4756    multi_reduce_step(erg,los,c);
4757    }
4758//     reduction_step *rs=create_reduction_step(erg, los, c);
4759//     rs->reduce(los,erg.to_reduce_l,erg.to_reduce_u);
4760//     finalize_reduction_step(rs);
4761                 
4762    int deleted=multi_reduction_clear_zeroes(los, losl, erg.to_reduce_l, erg.to_reduce_u);
4763    if(erg.fromS==FALSE)
4764      curr_pos=max(erg.to_reduce_u,erg.reduce_by);
4765    else
4766      curr_pos=erg.to_reduce_u;
4767    losl -= deleted;
4768    curr_pos -= deleted;
4769
4770    //Print("deleted %i \n",deleted);
4771    sort_region_down(los, erg.to_reduce_l, erg.to_reduce_u-deleted, c);
4772//   sort_region_down(los, 0, losl-1, c);
4773    //  qsort(los,losl,sizeof(red_object),red_object_better_gen);
4774    if(erg.expand)
4775    {
4776#ifdef FIND_DETERMINISTIC
4777      int i;
4778      for(i=0;c->expandS[i];i++);
4779      c->expandS=(poly*) omrealloc(c->expandS,(i+2)*sizeof(poly));
4780      c->expandS[i]=erg.expand;
4781      c->expandS[i+1]=NULL;
4782#else
4783      add_to_reductors(c,erg.expand,erg.expand_length);
4784#endif
4785    }
4786     
4787  }
4788  return;
4789}
4790void red_object::flatten(){
4791  if (sum!=NULL)
4792  {
4793
4794 
4795    if(kBucketGetLm(sum->ac->bucket)!=NULL){
4796      number mult_my=n_Mult(sum->c_my,sum->ac->multiplied,currRing);
4797      poly add_this;
4798      if(!nIsOne(mult_my))
4799        kBucket_Mult_n(bucket,mult_my);
4800      int len;
4801      poly clear_into;
4802      kBucketClear(sum->ac->bucket,&clear_into,&len);
4803      if(sum->ac->counter>1){
4804        add_this=pCopy(clear_into);
4805        kBucketInit(sum->ac->bucket,clear_into,len);
4806      }
4807      else
4808        add_this=clear_into;
4809      if(!nIsOne(sum->c_ac))
4810        pMult_nn(add_this, sum->c_ac);
4811     
4812      kBucket_Add_q(bucket,add_this, &len);
4813       nDelete(&mult_my);
4814     
4815    }
4816    nDelete(&sum->c_ac);
4817    nDelete(&sum->c_my);
4818   
4819    sum->ac->decrease_counter();
4820    delete sum;
4821    p=kBucketGetLm(bucket);
4822    sum=NULL;
4823  }
4824  assume(p==kBucketGetLm(bucket));
4825  assume(sum==NULL);
4826}
4827void red_object::validate(){
4828  BOOLEAN flattened=FALSE;
4829  if(sum!=NULL)
4830  {
4831    poly lm=kBucketGetLm(bucket);
4832    poly lm_ac=kBucketGetLm(sum->ac->bucket);
4833    if ((lm_ac==NULL)||((lm!=NULL) && (pLmCmp(lm,lm_ac)!=-1))){
4834      flatten();
4835      assume(sum==NULL);
4836      flattened=TRUE;
4837      p=kBucketGetLm(bucket);
4838      if (p!=NULL)
4839        sev=pGetShortExpVector(p);
4840    } 
4841    else
4842    {
4843 
4844      p=lm_ac;
4845      assume(sum->ac->sev==pGetShortExpVector(p));
4846      sev=sum->ac->sev;
4847    }
4848   
4849  }
4850  else{
4851    p=kBucketGetLm(bucket);
4852    if(p)
4853    sev=pGetShortExpVector(p);
4854  }
4855  assume((sum==NULL)||(kBucketGetLm(sum->ac->bucket)!=NULL));
4856}
4857int red_object::clear_to_poly(){
4858  flatten();
4859  int l;
4860  kBucketClear(bucket,&p,&l);
4861  return l;
4862}
4863
4864 
4865
4866void red_object::adjust_coefs(number c_r, number c_ac_r){
4867  assume(this->sum!=NULL);
4868  number n1=nMult(sum->c_my, c_ac_r);
4869  number n2=nMult(sum->c_ac,c_r);
4870  nDelete(&sum->c_my);
4871  nDelete(&sum->c_ac);
4872 
4873  int ct = ksCheckCoeff(&n1, &n2);
4874  sum->c_my=n1;
4875  sum->c_ac=nNeg(n2);
4876  //  nDelete(&n2);
4877 
4878
4879}
4880int red_object::guess_quality(calc_dat* c){
4881    //works at the moment only for lenvar 1, because in different
4882    //case, you have to look on coefs
4883    int s=0;
4884    if (c->is_char0)
4885      s=kSBucketLength(bucket);
4886    else 
4887      s=bucket_guess(bucket);
4888    if (sum!=NULL){
4889      if (c->is_char0)
4890      s+=kSBucketLength(sum->ac->bucket);
4891    else 
4892      s+=bucket_guess(sum->ac->bucket);
4893    }
4894    return s;
4895}
4896void reduction_step::reduce(red_object* r, int l, int u){}
4897void simple_reducer::target_is_no_sum_reduce(red_object & ro){
4898  kBucketPolyRed(ro.bucket,p,
4899                 p_len,
4900                 c->strat->kNoether);
4901}
4902
4903void simple_reducer::target_is_a_sum_reduce(red_object & ro){
4904  pTest(p);
4905  kbTest(ro.bucket);
4906  kbTest(ro.sum->ac->bucket);
4907  assume(ro.sum!=NULL);
4908  assume(ro.sum->ac!=NULL);
4909  if(ro.sum->ac->last_reduction_id!=reduction_id){
4910    number n1=kBucketPolyRed(ro.sum->ac->bucket,p, p_len, c->strat->kNoether);
4911    number n2=nMult(n1,ro.sum->ac->multiplied);
4912    nDelete(&ro.sum->ac->multiplied);
4913    nDelete(&n1);
4914    ro.sum->ac->multiplied=n2;
4915    poly lm=kBucketGetLm(ro.sum->ac->bucket);
4916    if (lm)
4917      ro.sum->ac->sev=pGetShortExpVector(lm);
4918    ro.sum->ac->last_reduction_id=reduction_id;
4919  }
4920  ro.sev=ro.sum->ac->sev;
4921  ro.p=kBucketGetLm(ro.sum->ac->bucket);
4922}
4923void simple_reducer::reduce(red_object* r, int l, int u){
4924  this->pre_reduce(r,l,u);
4925  int i;
4926//debug start
4927  int im;
4928//  for(im=l;im<=u;im++)
4929  //  assume(is_valid_ro(r[im]));
4930 
4931
4932//debug end
4933
4934  for(i=l;i<=u;i++){
4935 
4936
4937    if(r[i].sum==NULL)
4938      this->target_is_no_sum_reduce(r[i]);
4939
4940    else 
4941    {
4942      this->target_is_a_sum_reduce(r[i]);
4943      //reduce and adjust multiplied
4944      r[i].sum->ac->last_reduction_id=reduction_id;
4945     
4946    }
4947    //most elegant would be multimethods at this point and subclassing
4948    //red_object for sum
4949 
4950  }
4951  for(i=l;i<=u;i++){
4952    r[i].validate();
4953    #ifdef TGB_DEBUG
4954    if (r[i].sum) r[i].sev=r[i].sum->ac->sev;
4955
4956    #endif
4957      }
4958}
4959reduction_step::~reduction_step(){}
4960simple_reducer::~simple_reducer(){
4961  if(fill_back!=NULL)
4962  {
4963    kBucketInit(fill_back,p,p_len);
4964  }
4965  fill_back=NULL;
4966   
4967}
4968 join_simple_reducer::~join_simple_reducer(){
4969   if(fill_back!=NULL)
4970   {
4971     kBucketInit(fill_back,p,p_len);
4972   }
4973   fill_back=NULL;
4974   
4975}
4976void multi_reduce_step(find_erg & erg, red_object* r, calc_dat* c){
4977  static int id=0;
4978  id++;
4979
4980  int rn=erg.reduce_by;
4981  poly red;
4982  int red_len;
4983  simple_reducer* pointer;
4984  BOOLEAN woc=FALSE;
4985  if(erg.fromS){
4986    red=c->strat->S[rn];
4987    red_len=c->strat->lenS[rn];
4988   
4989  }
4990  else
4991  {
4992    r[rn].flatten();
4993    kBucketClear(r[rn].bucket,&red,&red_len);
4994    if (!rField_is_Zp(c->r))
4995    {
4996      pContent(red);
4997      pCleardenom(red);//should be unnecessary
4998     
4999    }
5000    pNormalize(red);
5001  }
5002  if (erg.to_reduce_u-erg.to_reduce_l>5){
5003    woc=TRUE;
5004    // poly m=pOne();
5005    poly m=c->tmp_lm;
5006    pSetCoeff(m,nInit(1));
5007    for(int i=1;i<=pVariables;i++)
5008      pSetExp(m,i,(pGetExp(r[erg.to_reduce_l].p, i)-pGetExp(red,i)));
5009    pSetm(m);
5010    poly red_cp=ppMult_mm(red,m);
5011   
5012    if(!erg.fromS){
5013      kBucketInit(r[rn].bucket,red,red_len);
5014    }
5015    //now reduce the copy
5016    //static poly redNF2 (poly h,calc_dat* c , int &len, number&  m,int n)
5017    redTailShort(red_cp,c->strat);
5018    //number mul;
5019    // red_len--;
5020//     red_cp->next=redNF2(red_cp->next,c,red_len,mul,c->average_length);
5021//     pSetCoeff(red_cp,nMult(red_cp->coef,mul));
5022//     nDelete(&mul);
5023//     red_len++;
5024    red=red_cp;
5025    red_len=pLength(red);
5026    // pDelete(&m);
5027   
5028  }
5029  int i;
5030
5031
5032  int red_c=0;
5033  if(red_len>2*c->average_length){
5034    for(i=erg.to_reduce_l;i<=erg.to_reduce_u;i++){
5035      if((r[i].sum==NULL) ||(r[i].sum->ac->counter<=AC_FLATTEN)) red_c++;
5036    }
5037  }
5038  if (red_c>=AC_NEW_MIN)
5039    pointer=new join_simple_reducer(red,red_len,r[erg.to_reduce_l].p);
5040  else
5041    pointer=new simple_reducer(red,red_len,c);
5042
5043  if ((!woc) && (!erg.fromS))
5044    pointer->fill_back=r[rn].bucket;
5045  else
5046    pointer->fill_back=NULL;
5047  pointer->reduction_id=id;
5048  pointer->c=c;
5049
5050  pointer->reduce(r,erg.to_reduce_l, erg.to_reduce_u);
5051  if(woc) pDelete(&pointer->p);
5052  delete pointer;
5053 
5054};
5055
5056void join_simple_reducer::target_is_no_sum_reduce(red_object & ro){
5057 
5058  ro.sum=new formal_sum_descriptor();
5059  ro.sum->ac=ac;
5060  ac->counter++;
5061  kBucket_pt bucket=ro.bucket;
5062  poly a1 = pNext(p), lm = kBucketExtractLm(bucket);
5063  BOOLEAN reset_vec=FALSE;
5064  number rn;
5065  assume(a1!=NULL);
5066  number an = pGetCoeff(p), bn = pGetCoeff(lm);
5067  lm->next=NULL;
5068  int ct = ksCheckCoeff(&an, &bn);
5069  ro.sum->c_ac=nNeg(bn);
5070  ro.sum->c_my=an;
5071  assume(nIsZero(nAdd(nMult(ro.sum->c_my,lm->coef),nMult(p->coef,ro.sum->c_ac) )));
5072  if (p_GetComp(p, bucket->bucket_ring) != p_GetComp(lm, bucket->bucket_ring))
5073  {
5074    p_SetCompP(a1, p_GetComp(lm, bucket->bucket_ring), bucket->bucket_ring);
5075    reset_vec = TRUE;
5076    p_SetComp(lm, p_GetComp(p, bucket->bucket_ring), bucket->bucket_ring);
5077    p_Setm(lm, bucket->bucket_ring);
5078  }
5079
5080
5081 
5082
5083  p_DeleteLm(&lm, bucket->bucket_ring);
5084  if (reset_vec) p_SetCompP(a1, 0, bucket->bucket_ring);
5085  kbTest(bucket);
5086
5087}
5088
5089  reduction_accumulator::reduction_accumulator(poly p, int p_len, poly high_to){
5090    //sev needs to be removed from interfaces,makes no sense
5091   
5092
5093    poly my=pOne();
5094    counter=0;
5095   
5096    for(int i=1;i<=pVariables;i++)
5097      pSetExp(my,i,(pGetExp(high_to, i)-pGetExp(p,i)));
5098    pSetm(my);
5099
5100    last_reduction_id=-1;
5101    multiplied=nInit(1);
5102    bucket=kBucketCreate(currRing);
5103    poly a=pMult_mm(pCopy(p->next),my);
5104
5105    this->sev=pGetShortExpVector(a);
5106    kBucketInit(bucket, a,p_len-1);
5107    pDelete(&my);
5108  }
5109void simple_reducer:: pre_reduce(red_object* r, int l, int u){}
5110void join_simple_reducer:: pre_reduce(red_object* r, int l, int u){
5111  for(int i=l;i<=u;i++)
5112    {
5113      if (r[i].sum){
5114        if(r[i].sum->ac->counter<=AC_FLATTEN) r[i].flatten();
5115       
5116      }
5117    }
5118}
Note: See TracBrowser for help on using the repository browser.