source: git/Singular/tgb.cc @ 2cd98b

spielwiese
Last change on this file since 2cd98b was 2cd98b, checked in by Michael Brickenstein <bricken@…>, 20 years ago
*bricken: multiplication with 1 faster git-svn-id: file:///usr/local/Singular/svn/trunk@7550 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 110.6 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  if(nIsOne(factor))
2538    return;
2539  mac_mult_cons(mp[row],factor);
2540}
2541void tgb_sparse_matrix::free_row(int row, BOOLEAN free_non_zeros){
2542  if(free_non_zeros)
2543    mac_destroy(mp[row]);
2544  else
2545  {
2546    while(mp[row])
2547    {
2548     
2549      mac_poly next=mp[row]->next;
2550      delete mp[row];
2551      mp[row]=next;
2552    }
2553  }
2554  mp[row]=NULL;
2555}
2556//transfers ownership of m to mat
2557void init_with_mac_poly(tgb_sparse_matrix* mat, int row, mac_poly m){
2558  assume(mat->mp[row]==NULL);
2559  mat->mp[row]=m;
2560#ifdef TGB_DEBUG
2561  mac_poly r=m;
2562  while(r){
2563    assume(r->exp<mat->columns);
2564    r=r->next;
2565  }
2566#endif
2567}
2568poly free_row_to_poly(tgb_sparse_matrix* mat, int row, poly* monoms, int monom_index){
2569  poly p=NULL;
2570  poly* set_this=&p;
2571  mac_poly r=mat->mp[row];
2572  mat->mp[row]=NULL;
2573  while(r)
2574  {
2575    (*set_this)=pLmInit(monoms[monom_index-1-r->exp]);
2576    pSetCoeff((*set_this),r->coef);
2577    set_this=&((*set_this)->next);
2578    r=r->next;
2579   
2580  }
2581  return p;
2582
2583}
2584
2585void simple_gauss(tgb_sparse_matrix* mat, calc_dat* c){
2586  int col, row;
2587  int* row_cache=(int*) omalloc(mat->get_rows()*sizeof(int));
2588  col=0;
2589  row=0;
2590  int i;
2591  int pn=mat->get_rows();
2592  int matcol=mat->get_columns();
2593  int* area=(int*) omalloc(sizeof(int)*((matcol-1)/bundle_size+1));
2594  const int max_area_index=(matcol-1)/bundle_size;
2595    //rows are divided in areas
2596  //if row begins with columns col, it is located in [area[col/bundle_size],area[col/bundle_size+1]-1]
2597  assume(pn>0);
2598  //first clear zeroes
2599  for(i=0;i<pn;i++)
2600  {
2601    if(mat->zero_row(i))
2602    {
2603      mat->perm_rows(i,pn-1);
2604      pn--;
2605      if(i!=pn){i--;}
2606    }
2607 
2608  }
2609  mat->sort_rows();
2610  for(i=0;i<pn;i++)
2611  {
2612      row_cache[i]=mat->min_col_not_zero_in_row(i);
2613      // Print("row_cache:%d\n",row_cache[i]);
2614  }
2615  int last_area=-1;
2616  for(i=0;i<pn;i++)
2617  {
2618    int this_area=row_cache[i]/bundle_size;
2619    assume(this_area>=last_area);
2620    if(this_area>last_area)
2621    {
2622      int j;
2623      for(j=last_area+1;j<=this_area;j++)
2624        area[j]=i;
2625      last_area=this_area;
2626    }
2627  }
2628  for(i=last_area+1;i<=max_area_index;i++)
2629  {
2630    area[i]=pn;
2631  }
2632  while(row<pn-1){
2633    //row is the row where pivot should be
2634    // row== pn-1 means we have only to act on one row so no red nec.
2635    //we assume further all rows till the pn-1 row are non-zero
2636   
2637    //select column
2638   
2639    //col=mat->min_col_not_zero_in_row(row);
2640    int max_in_area;
2641    {
2642      int tai=row_cache[row]/bundle_size;
2643      assume(tai<=max_area_index);
2644      if(tai==max_area_index)
2645        max_in_area=pn-1;
2646      else
2647        max_in_area=area[tai+1]-1;
2648    }
2649    assume(row_cache[row]==mat->min_col_not_zero_in_row(row));
2650    col=row_cache[row];
2651
2652   
2653    assume(col!=matcol);
2654    int found_in_row;
2655   
2656    found_in_row=row;
2657    BOOLEAN must_reduce=FALSE;
2658    assume(pn<=mat->get_rows());
2659    for(i=row+1;i<=max_in_area;i++){
2660      int first;//=mat->min_col_not_zero_in_row(i);
2661      assume(row_cache[i]==mat->min_col_not_zero_in_row(i));
2662      first=row_cache[i];
2663      assume(first!=matcol);
2664      if(first<col)
2665      {
2666        col=first;
2667        found_in_row=i;
2668        must_reduce=FALSE;
2669      }
2670      else {
2671        if(first==col)
2672          must_reduce=TRUE;
2673      }
2674    }
2675    //select pivot
2676    int act_l=mat->non_zero_entries(found_in_row);
2677    for(i=found_in_row+1;i<=max_in_area;i++){
2678      assume(mat->min_col_not_zero_in_row(i)>=col);
2679      int first;
2680      assume(row_cache[i]==mat->min_col_not_zero_in_row(i));
2681      first=row_cache[i];
2682      assume(first!=matcol);
2683      //      if((!(mat->is_zero_entry(i,col)))&&(mat->non_zero_entries(i)<act_l))
2684      int nz;
2685      if((row_cache[i]==col)&&((nz=mat->non_zero_entries(i))<act_l))
2686      {
2687        found_in_row=i;
2688        act_l=nz;
2689      }
2690
2691    }
2692
2693    mat->perm_rows(row,found_in_row);
2694    int h=row_cache[row];
2695    row_cache[row]=row_cache[found_in_row];
2696    row_cache[found_in_row]=h;
2697
2698
2699
2700    if(!must_reduce){
2701      row++;
2702      continue;
2703    }
2704    //reduction
2705    //must extract content and normalize here
2706    mat->row_normalize(row);
2707
2708    //for(i=row+1;i<pn;i++){
2709    for(i=max_in_area;i>row;i--)
2710    {
2711      int col_area_index=col/bundle_size;
2712      assume(col_area_index<=max_area_index);
2713      assume(mat->min_col_not_zero_in_row(i)>=col);
2714      int first;
2715      assume(row_cache[i]==mat->min_col_not_zero_in_row(i));
2716      first=row_cache[i];
2717      assume(first!=matcol);
2718      if(row_cache[i]==col)
2719      {
2720       
2721        number c1=nNeg(nCopy(mat->get(i,col)));
2722        number c2=mat->get(row,col);
2723        number n1=c1;
2724        number n2=c2;
2725
2726        ksCheckCoeff(&n1,&n2);
2727        nDelete(&c1);
2728        mat->mult_row(i,n2);
2729        mat->add_lambda_times_row(i,row,n1);
2730        nDelete(&n1);
2731        nDelete(&n2);
2732        assume(mat->is_zero_entry(i,col));
2733        row_cache[i]=mat->min_col_not_zero_in_row(i);
2734        assume(mat->min_col_not_zero_in_row(i)>col);
2735        if(row_cache[i]==matcol)
2736        {
2737          int index;
2738          index=i;
2739          int last_in_area;
2740          int this_cai=col_area_index;
2741          while(this_cai<max_area_index)
2742          {
2743            last_in_area=area[this_cai+1]-1;
2744            int h_c=row_cache[last_in_area];
2745            row_cache[last_in_area]=row_cache[index];
2746            row_cache[index]=h_c;
2747            mat->perm_rows(index,last_in_area);
2748            index=last_in_area;
2749            this_cai++;
2750            area[this_cai]--;
2751          }
2752          mat->perm_rows(index,pn-1);
2753          row_cache[index]=row_cache[pn-1];
2754          row_cache[pn-1]=matcol;
2755          pn--;
2756        }
2757        else 
2758        {
2759          int index;
2760          index=i;
2761          int last_in_area;
2762          int this_cai=col_area_index;
2763          int final_cai=row_cache[index]/bundle_size;
2764          assume(final_cai<=max_area_index);
2765          while(this_cai<final_cai)
2766          {
2767            last_in_area=area[this_cai+1]-1;
2768            int h_c=row_cache[last_in_area];
2769            row_cache[last_in_area]=row_cache[index];
2770            row_cache[index]=h_c;
2771            mat->perm_rows(index,last_in_area);
2772            index=last_in_area;
2773            this_cai++;
2774            area[this_cai]--;
2775          }
2776        }
2777      }
2778      else
2779        assume(mat->min_col_not_zero_in_row(i)>col);
2780    }
2781
2782//     for(i=row+1;i<pn;i++)
2783//     {
2784//       assume(mat->min_col_not_zero_in_row(i)==row_cache[i]);
2785//       // if(mat->zero_row(i))
2786//       assume(matcol==mat->get_columns());
2787//       if(row_cache[i]==matcol)
2788//       {
2789//      assume(mat->zero_row(i));
2790//      mat->perm_rows(i,pn-1);
2791//      row_cache[i]=row_cache[pn-1];
2792//      row_cache[pn-1]=matcol;
2793//      pn--;
2794//      if(i!=pn){i--;}
2795//       }
2796//     }
2797#ifdef TGB_DEBUG
2798  {
2799  int last=-1;
2800  for(i=0;i<pn;i++)
2801  {
2802    int act=mat->min_col_not_zero_in_row(i);
2803    assume(act>last);
2804   
2805  }
2806  for(i=pn;i<mat->get_rows();i++)
2807  {
2808    assume(mat->zero_row(i));
2809   
2810  }
2811 
2812
2813  }
2814#endif
2815    row++;
2816  }
2817  omfree(area);
2818  omfree(row_cache);
2819}
2820void simple_gauss2(tgb_matrix* mat){
2821  int col, row;
2822  col=0;
2823  row=0;
2824  int i;
2825  int pn=mat->get_rows();
2826  assume(pn>0);
2827  //first clear zeroes
2828//   for(i=0;i<pn;i++)
2829//   {
2830//     if(mat->zero_row(i))
2831//     {
2832//       mat->perm_rows(i,pn-1);
2833//       pn--;
2834//       if(i!=pn){i--;}
2835//     }
2836//   }
2837  while((row<pn-1)&&(col<mat->get_columns())){
2838    //row is the row where pivot should be
2839    // row== pn-1 means we have only to act on one row so no red nec.
2840    //we assume further all rows till the pn-1 row are non-zero
2841   
2842    //select column
2843   
2844    //    col=mat->min_col_not_zero_in_row(row);
2845    assume(col!=mat->get_columns());
2846    int found_in_row=-1;
2847   
2848    //    found_in_row=row;
2849    assume(pn<=mat->get_rows());
2850    for(i=row;i<pn;i++)
2851    {
2852      //    int first=mat->min_col_not_zero_in_row(i);
2853      //  if(first<col)
2854      if(!(mat->is_zero_entry(i,col))){
2855       
2856        found_in_row=i;
2857        break;
2858      }
2859    }
2860    if(found_in_row!=-1)
2861    {
2862    //select pivot
2863      int act_l=mat->non_zero_entries(found_in_row);
2864      for(i=i+1;i<pn;i++)
2865      {
2866        int vgl;
2867        assume(mat->min_col_not_zero_in_row(i)>=col);
2868        if((!(mat->is_zero_entry(i,col)))&&((vgl=mat->non_zero_entries(i))<act_l))
2869        {
2870          found_in_row=i;
2871          act_l=vgl;
2872        }
2873       
2874      }
2875      mat->perm_rows(row,found_in_row);
2876     
2877     
2878      //reduction
2879      for(i=row+1;i<pn;i++){
2880        assume(mat->min_col_not_zero_in_row(i)>=col);
2881        if(!(mat->is_zero_entry(i,col)))
2882        {
2883         
2884          number c1=nNeg(nCopy(mat->get(i,col)));
2885          number c2=mat->get(row,col);
2886          number n1=c1;
2887          number n2=c2;
2888         
2889          ksCheckCoeff(&n1,&n2);
2890          nDelete(&c1);
2891          mat->mult_row(i,n2);
2892          mat->add_lambda_times_row(i,row,n1);
2893          assume(mat->is_zero_entry(i,col));
2894         
2895        } 
2896        assume(mat->min_col_not_zero_in_row(i)>col);
2897      }
2898      row++;
2899    }
2900    col++;
2901    // for(i=row+1;i<pn;i++)
2902//     {
2903//       if(mat->zero_row(i))
2904//       {
2905//      mat->perm_rows(i,pn-1);
2906//      pn--;
2907//      if(i!=pn){i--;}
2908//       }
2909//     }
2910
2911  }
2912}
2913
2914static tgb_matrix* build_matrix(poly* p,int p_index,poly* done, int done_index, calc_dat* c){
2915  tgb_matrix* t=new tgb_matrix(p_index,done_index);
2916  int i, pos;
2917  //  Print("\n 0:%s\n",pString(done[done_index-1]));
2918  //Print("\n 1:%s\n",pString(done[done_index-2]));
2919  assume((!(pLmEqual(done[done_index-1],done[done_index-2]))));
2920#ifdef TGB_DEGUG
2921  for(i=0;i<done_index;i++)
2922  {
2923    int j;
2924    for(j=0;j<i;j++)
2925    {
2926      assume((!(pLmEqual(done[i],done[j]))));
2927    }
2928  }
2929#endif
2930  for(i=0;i<p_index;i++)
2931  { 
2932    // Print("%i ter Eintrag:%s\n",i,pString(p[i]));
2933    poly p_i=p[i];
2934    while(p_i)
2935    {
2936
2937      int v=-1;
2938      pos=posInPolys (done, done_index, p_i,c);
2939      if((done_index>pos)&&(pLmEqual(p_i,done[pos])))
2940        v=pos;
2941      if((pos>0) &&(pLmEqual(p_i,done[pos-1])))
2942        v=pos-1;
2943      assume(v!=-1);
2944      //v is ascending ordered, we need descending order
2945      v=done_index-1-v;
2946      number nt=t->get(i,v);
2947      nDelete(&nt);
2948      t->set(i,v,nCopy(p_i->coef));
2949      p_i=p_i->next;
2950    }
2951  }
2952  return t;
2953}
2954static tgb_sparse_matrix* build_sparse_matrix(poly* p,int p_index,poly* done, int done_index, calc_dat* c){
2955  tgb_sparse_matrix* t=new tgb_sparse_matrix(p_index,done_index,c->r);
2956  int i, pos;
2957  //  Print("\n 0:%s\n",pString(done[done_index-1]));
2958  //Print("\n 1:%s\n",pString(done[done_index-2]));
2959  //  assume((!(pLmEqual(done[done_index-1],done[done_index-2]))));
2960#ifdef TGB_DEGUG
2961  for(i=0;i<done_index;i++)
2962  {
2963    int j;
2964    for(j=0;j<i;j++)
2965    {
2966      assume((!(pLmEqual(done[i],done[j]))));
2967    }
2968  }
2969#endif
2970  for(i=0;i<p_index;i++)
2971  { 
2972    // Print("%i ter Eintrag:%s\n",i,pString(p[i]));
2973    mac_poly m=NULL;
2974    mac_poly* set_this=&m;
2975    poly p_i=p[i];
2976    while(p_i)
2977    {
2978
2979      int v=-1;
2980      pos=posInPolys (done, done_index, p_i,c);
2981      if((done_index>pos)&&(pLmEqual(p_i,done[pos])))
2982        v=pos;
2983      if((pos>0) &&(pLmEqual(p_i,done[pos-1])))
2984        v=pos-1;
2985      assume(v!=-1);
2986      //v is ascending ordered, we need descending order
2987      v=done_index-1-v;
2988      (*set_this)=new mac_poly_r();
2989      (*set_this)->exp=v;
2990       
2991      (*set_this)->coef=nCopy(p_i->coef);
2992       set_this=&(*set_this)->next;
2993       p_i=p_i->next;
2994
2995    }
2996    init_with_mac_poly(t,i,m);
2997  }
2998  return t;
2999}
3000
3001
3002static int retranslate(poly* m,tgb_sparse_matrix* mat,poly* done, calc_dat* c){
3003  int i;
3004  int m_index=0;
3005  for(i=0;i<mat->get_rows();i++)
3006  {
3007    if(mat->zero_row(i))
3008    {
3009      mat->free_row(i);
3010      continue;
3011    }
3012    m[m_index++]= free_row_to_poly(mat, i, done, mat->get_columns());
3013
3014  }
3015
3016  delete mat;
3017  return m_index;
3018
3019}
3020
3021//returns m_index and destroys mat
3022static int retranslate(poly* m,tgb_matrix* mat,poly* done, calc_dat* c){
3023  int i;
3024  int m_index=0;
3025  for(i=0;i<mat->get_rows();i++)
3026  {
3027    if(mat->zero_row(i))
3028    {
3029      mat->free_row(i);
3030      continue;
3031    }
3032   
3033    m[m_index]=pInit();
3034    int v=mat->min_col_not_zero_in_row(i);
3035    //v=done_index-1-pos; => pos=done_index-1-v=mat->get_columns()-1-v
3036    int pos=mat->get_columns()-1-v;
3037    int* ev=(int*) omalloc((c->r->N+1)*sizeof(int));
3038    pGetExpV(done[pos],ev);
3039    pSetExpV(m[m_index],ev);
3040    omfree(ev);
3041   
3042    poly p=m[m_index];
3043    pSetCoeff(p,mat->get(i,v));
3044    while((v=mat->next_col_not_zero(i,v))!=mat->get_columns())
3045    {
3046      poly pn=pInit();
3047     
3048      //v=done_index-1-pos; => pos=done_index-1-v=mat->get_columns()-1-v
3049      pos=mat->get_columns()-1-v;
3050      ev=(int*) omalloc((c->r->N+1)*sizeof(int));
3051      pGetExpV(done[pos],ev);
3052      pSetExpV(pn,ev);
3053      omfree(ev);
3054      pSetCoeff(pn,mat->get(i,v));
3055      p->next=pn;
3056      p=pn;
3057    }
3058    p->next=NULL;
3059    mat->free_row(i, FALSE);
3060    m_index++;
3061  }
3062
3063  delete mat;
3064  return m_index;
3065
3066}
3067static void go_on_F4 (calc_dat* c){
3068  //set limit of 1000 for multireductions, at the moment for
3069  //programming reasons
3070  int max_par;
3071  if (c->is_homog)
3072    max_par=PAR_N_F4;
3073  else
3074    max_par=200;
3075  int done_size=max_par*2;
3076  poly* done=(poly*) omalloc(done_size*sizeof(poly));
3077  int done_index=0; //done_index must always be smaller than done_size
3078  int chosen_size=max_par*2;
3079  monom_poly* chosen=(monom_poly*) omalloc(chosen_size*sizeof(monom_poly));
3080  int chosen_index=0;
3081  //  monom_poly* vgl=(monom_poly*) omalloc(chosen_size*sizeof(monom_poly));
3082  int i=0;
3083  c->average_length=0;
3084  for(i=0;i<c->n;i++){
3085    c->average_length+=c->lengths[i];
3086  }
3087  c->average_length=c->average_length/c->n;
3088  i=0;
3089  poly* p;
3090  int nfs=0;
3091  int curr_deg=-1;
3092
3093  //choose pairs and preprocess symbolically
3094  while(chosen_index<max_par)
3095  {
3096   
3097    //    sorted_pair_node* s=c->apairs[c->pair_top];
3098    sorted_pair_node* s;
3099    if(c->pair_top>=0)
3100      s=top_pair(c);//here is actually chain criterium done
3101    else
3102      s=NULL;
3103    if (!s) break;
3104    nfs++;
3105    if(curr_deg>=0)
3106    {
3107      if (s->deg >curr_deg) break;
3108    }
3109
3110    else curr_deg=s->deg;
3111    quick_pop_pair(c);
3112    if(s->i>=0)
3113    {
3114      //replace_pair(s->i,s->j,c);
3115      if(s->i==s->j) 
3116      {
3117        free_sorted_pair_node(s,c->r);
3118        continue;
3119      }
3120    }
3121    assume(s->i>=0);
3122    monom_poly h;
3123    BOOLEAN only_free=FALSE;
3124    if(s->i>=0)
3125    {
3126     
3127      poly lcm=pOne();
3128     
3129      pLcm(c->S->m[s->i], c->S->m[s->j], lcm);
3130      pSetm(lcm);
3131      assume(lcm!=NULL);
3132      poly factor1=pCopy(lcm);
3133      pExpVectorSub(factor1,c->S->m[s->i]);
3134      poly factor2=pCopy(lcm);
3135      pExpVectorSub(factor2,c->S->m[s->j]);
3136
3137      if(done_index>=done_size)
3138      {
3139        done_size+=max_par;
3140        done=(poly*) omrealloc(done,done_size*sizeof(poly));
3141      }
3142      done[done_index++]=lcm;
3143      if(chosen_index+1>=chosen_size)
3144      {
3145        //max_par must be greater equal 2
3146        chosen_size+=max(max_par,2);
3147        chosen=(monom_poly*) omrealloc(chosen,chosen_size*sizeof(monom_poly));
3148      }
3149      h.f=c->S->m[s->i];
3150      h.m=factor1;
3151      chosen[chosen_index++]=h;
3152      h.f=c->S->m[s->j];
3153      h.m=factor2;
3154      chosen[chosen_index++]=h;
3155    }
3156    else
3157    {
3158      if(chosen_index>=chosen_size)
3159      {
3160        chosen_size+=max_par;
3161        chosen=(monom_poly*) omrealloc(chosen,chosen_size*sizeof(monom_poly));
3162      }
3163      h.f=s->lcm_of_lm;
3164      h.m=pOne();
3165      //pSetm(h.m); done by pOne
3166      chosen[chosen_index++]=h;
3167      //must carefull remember to destroy such a h;
3168      poly_list_node* next=c->to_destroy;
3169     
3170      c->to_destroy=(poly_list_node*) omalloc(sizeof(poly_list_node));
3171      c->to_destroy->p=h.f;
3172      c->to_destroy->next=next;
3173      only_free=TRUE;
3174    }
3175
3176    if(s->i>=0)
3177      now_t_rep(s->j,s->i,c);
3178
3179    if(!(only_free))
3180      free_sorted_pair_node(s,c->r);
3181    else
3182      omfree(s);
3183   
3184 
3185
3186  }
3187  c->normal_forms+=nfs;
3188  if (TEST_OPT_PROT)
3189      Print("M[%i, ",nfs);
3190  //next Step, simplify all pairs
3191  for(i=0;i<chosen_index;i++)
3192  {
3193    //    PrintS("simplifying ");
3194    //Print("from %s",pString(chosen[i].m));
3195    //Print(", %s", pString(chosen[i].f));
3196     simplify(chosen[i],c);
3197    //Print(" to %s",pString(chosen[i].m));
3198    //Print(", %s \n", pString(chosen[i].f));
3199  }
3200 
3201  //next Step remove duplicate entries
3202  qsort(chosen,chosen_index,sizeof(monom_poly),monom_poly_crit);
3203  int pos=0;
3204  for(i=1;i<chosen_index;i++)
3205  {
3206    if(((chosen[i].f!=chosen[pos].f))||(!(pLmEqual(chosen[i].m,chosen[pos].m))))
3207      chosen[++pos]=chosen[i];
3208    else pDelete(&(chosen[i].m));
3209  }
3210  if(chosen_index>0)
3211    chosen_index=pos+1;
3212  //next step process polys
3213  int p_size=2*chosen_index;
3214  int p_index=0;
3215  p=(poly*) omalloc(p_size*sizeof(poly));
3216  for(p_index=0;p_index<chosen_index;p_index++)
3217  {
3218    p[p_index]=ppMult_mm(chosen[p_index].f,chosen[p_index].m);
3219  }
3220
3221  qsort(done, done_index,sizeof(poly),pLmCmp_func);
3222  pos=0;
3223  //Print("Done_index:%i",done_index);
3224  if(done_index>0)
3225  {
3226    pTest(done[0]);
3227  }
3228  for(i=1;i<done_index;i++)
3229  {
3230    pTest(done[i]);
3231    if((!(pLmEqual(done[i],done[pos]))))
3232      done[++pos]=done[i];
3233    else pDelete(&(done[i]));
3234  }
3235  if(done_index>0)
3236    done_index=pos+1;
3237#ifdef TGB_DEBUG
3238  for(i=0;i<done_index;i++)
3239  {
3240    int j;
3241    for(j=0;j<i;j++)
3242    {
3243      assume((!pLmEqual(done[j],done[i])));
3244    }
3245  }
3246#endif
3247#ifdef TGB_DEBUG
3248  for(i=0;i<done_index;i++)
3249  {
3250    pTest(done[i]);
3251  }
3252#endif
3253  poly* m;
3254  int m_index=0;
3255  int m_size=0;
3256  for(i=0;i<p_index;i++)
3257  {
3258    m_size+=pLength(p[i]);
3259  }
3260  m=(poly*) omalloc(m_size*sizeof(poly));
3261  //q=(poly*) omalloc(m_size*sizeof(poly));
3262
3263 
3264
3265  for(i=0;i<p_index;i++)
3266  {
3267
3268    poly p_i=p[i];
3269
3270    pTest(p[i]);
3271
3272    while(p_i)
3273    {
3274
3275      m[m_index]=pLmInit(p_i);
3276
3277      pSetCoeff(m[m_index],nInit(1));
3278
3279       p_i=p_i->next;
3280
3281      m_index++;
3282
3283    }
3284  }
3285
3286  int q_size=m_index;
3287  poly* q=(poly*) omalloc(q_size*sizeof(poly));
3288  int q_index=0;
3289  //next Step additional reductors
3290
3291  while(m_index>0)
3292  {
3293#ifdef TGB_DEBUG
3294     
3295      for(i=0;i<done_index;i++)
3296      {
3297        pTest(done[i]);
3298      }
3299#endif
3300
3301    qsort(m, m_index,sizeof(poly),pLmCmp_func);
3302
3303   
3304    pos=0;
3305    #ifdef TGB_DEBUG
3306     
3307      for(i=0;i<done_index;i++)
3308      {
3309       
3310        pTest(done[i]);
3311      }
3312#endif
3313    for(i=1;i<m_index;i++)
3314    {
3315      pTest(m[i]);
3316      pTest(m[pos]);
3317      if((!(pLmEqual(m[i],m[pos]))))
3318        m[++pos]=m[i];
3319      else pDelete(&(m[i]));
3320    }
3321    if(m_index>1)
3322      m_index=pos+1;
3323    if(done_size<done_index+m_index)
3324    {
3325      done_size=done_index+2*m_index;
3326      done=(poly*) omrealloc(done,done_size*sizeof(poly));
3327    }
3328    if(chosen_size<chosen_index+m_index)
3329    {
3330      chosen_size=chosen_index+2*m_index;
3331      chosen=(monom_poly*) omrealloc(chosen,chosen_size*sizeof(monom_poly));
3332    }
3333    q_index=0;
3334    if(q_size<m_index)
3335    {
3336      q_size=2*m_index;
3337      omfree(q);
3338      q=(poly*) omalloc(q_size*sizeof(poly));
3339    }
3340
3341    for(i=0;i<m_index;i++)
3342    {
3343
3344#ifdef TGB_DEBUG
3345      {
3346        int my_i;
3347        for(my_i=0;my_i<done_index;my_i++)
3348        {
3349          int my_j;
3350          for(my_j=0;my_j<my_i;my_j++)
3351          {
3352            assume((!pLmEqual(done[my_j],done[my_i])));
3353          }
3354        }
3355      }
3356#endif
3357      BOOLEAN in_done=FALSE;
3358      pTest(m[i]);
3359
3360      pos=posInPolys (done, done_index, m[i],c);
3361#ifdef TGB_DEBUG
3362      {
3363        int my_i;
3364        for (my_i=0;my_i<done_index;my_i++)
3365          pTest(done[my_i]);
3366      }
3367#endif     
3368      if(((done_index>pos)&&(pLmEqual(m[i],done[pos]))) ||(pos>0) &&(pLmEqual(m[i],done[pos-1])))
3369        in_done=TRUE;
3370      if (!(in_done))
3371      {
3372       
3373        int S_pos=kFindDivisibleByInS_easy(c->strat,m[i], pGetShortExpVector(m[i]));
3374        if(S_pos>=0)
3375        {
3376          monom_poly h;
3377          h.f=c->strat->S[S_pos];
3378          h.m=pOne();
3379          int* ev=(int*) omalloc((c->r->N+1)*sizeof(int));
3380          pGetExpV(m[i],ev);
3381          pSetExpV(h.m,ev);
3382          omfree(ev);
3383          pExpVectorSub(h.m,c->strat->S[S_pos]);
3384          simplify(h,c);
3385          q[q_index]=ppMult_mm(h.f,h.m);
3386          chosen[chosen_index++]=h;
3387          q_index++;
3388        }
3389        pTest(m[i]);
3390#ifdef TGB_DEBUG
3391        {
3392          int my_i;
3393          for (my_i=0;my_i<done_index;my_i++)
3394            pTest(done[my_i]);
3395        }
3396#endif     
3397        memmove(&(done[pos+1]),&(done[pos]), (done_index-pos)*sizeof(poly));
3398        done[pos]=m[i];
3399        done_index++;
3400#ifdef TGB_DEBUG
3401        {
3402          int my_i;
3403          for (my_i=0;my_i<done_index;my_i++)
3404          {
3405            //      Print("Position %i pos %i size %i\n",my_i,pos,done_index);
3406            pTest(done[my_i]);
3407          }
3408        }
3409#endif     
3410      }
3411      else
3412        pDelete(&m[i]);
3413#ifdef TGB_DEBUG
3414      {
3415        int my_i;
3416        for(my_i=0;my_i<done_index;my_i++)
3417        {
3418          pTest(done[my_i]);
3419          int my_j;
3420          for(my_j=0;my_j<my_i;my_j++)
3421          {
3422            assume((!pLmEqual(done[my_j],done[my_i])));
3423          }
3424        }
3425      }
3426#endif
3427    }
3428    if(p_size<p_index+q_index)
3429    {
3430      p_size=p_index+2*q_index;
3431      p=(poly*) omrealloc(p,p_size*sizeof(poly));
3432    }
3433    for (i=0;i<q_index;i++)
3434      p[p_index++]=q[i];
3435    m_index=0;
3436    int sum=0;
3437    for(i=0;i<p_index;i++)
3438    {
3439      sum+=pLength(p[i])-1;
3440    }
3441    if (m_size<sum)
3442    {
3443      omfree(m);
3444      m=(poly*) omalloc(sum*sizeof(poly));
3445    }
3446    m_size=sum;
3447    for(i=0;i<q_index;i++)
3448    {
3449      poly p_i=q[i]->next;
3450      while(p_i)
3451      {
3452        m[m_index]=pLmInit(p_i);
3453        pSetCoeff(m[m_index],nInit(1));
3454        p_i=p_i->next;
3455        m_index++;
3456      }
3457    }
3458    //qsort(done, done_index,sizeof(poly),pLmCmp_func);
3459#ifdef TGB_DEBUG
3460    for(i=0;i<done_index;i++)
3461    {
3462      pTest(done[i]);
3463    }
3464#endif
3465  }
3466#ifdef TGB_DEBUG
3467  for(i=0;i<done_index;i++)
3468  {
3469    int j;
3470    for(j=0;j<i;j++)
3471    {
3472      assume((!pLmEqual(done[j],done[i])));
3473    }
3474  }
3475#endif
3476  omfree(m);
3477  omfree(q);
3478  if (TEST_OPT_PROT)
3479    Print("Mat[%i x %i], ",chosen_index, done_index);
3480  //next Step build matrix
3481  #ifdef TGB_DEBUG
3482  for(i=0;i<done_index;i++)
3483  {
3484    int j;
3485    for(j=0;j<i;j++)
3486    {
3487      assume((!pLmEqual(done[j],done[i])));
3488    }
3489  }
3490#endif
3491  assume(p_index==chosen_index);
3492 
3493 //  tgb_matrix* mat=build_matrix(p,p_index,done, done_index,c);
3494 
3495//   simple_gauss2(mat);
3496  tgb_sparse_matrix* mat=build_sparse_matrix(p,p_index,done, done_index,c);
3497  simple_gauss(mat,c);
3498  m_size=mat->get_rows();
3499  m=(poly*) omalloc(m_size*sizeof(poly));
3500  m_index=retranslate(m,mat,done,c);
3501 
3502  mat=NULL;
3503  for(i=0;i<done_index;i++)
3504    pDelete(&done[i]);
3505  omfree(done);
3506  done=NULL;
3507  //next Step addElements to basis
3508  int F_plus_size=m_index;
3509  poly* F_plus=(poly*)omalloc(F_plus_size*sizeof(poly));
3510  int F_plus_index=0;
3511  int F_minus_size=m_index;
3512  poly* F_minus=(poly*) omalloc(F_minus_size*sizeof(poly));
3513  int F_minus_index=0;
3514
3515  //better algorithm replace p by its monoms, qsort,delete duplicates and binary search for testing if monom is contained in array
3516  qsort(p, p_index,sizeof(poly),pLmCmp_func);
3517  for(i=0;i<p_index;i++)
3518    pDelete(&p[i]->next);
3519  for(i=m_index-1;i>=0;--i)
3520  {
3521    int j;
3522    int pos=posInPolys (p,p_index, m[i],c);
3523    BOOLEAN minus=FALSE;
3524    if(((p_index>pos)&&(pLmEqual(m[i],p[pos]))) ||(pos>0) &&(pLmEqual(m[i],p[pos-1])))
3525      minus=TRUE;
3526   
3527    if(minus)
3528    {
3529      F_minus[F_minus_index++]=m[i];
3530      m[i]=NULL;
3531    }
3532    else
3533    {
3534      F_plus[F_plus_index++]=m[i];
3535      m[i]=NULL;
3536    }
3537  }
3538
3539//   for(i=m_index-1;i>=0;--i)
3540//   {
3541//     int j;
3542//     BOOLEAN minus=FALSE;
3543//     for(j=0;j<p_index;j++)
3544//       if (pLmEqual(p[j],m[i]))
3545//       {
3546//      minus=TRUE;
3547//      break;
3548//       }
3549//     if(minus)
3550//     {
3551//       F_minus[F_minus_index++]=m[i];
3552//       m[i]=NULL;
3553//     }
3554//     else
3555//     {
3556//       F_plus[F_plus_index++]=m[i];
3557//       m[i]=NULL;
3558//     }
3559//   }
3560  //in this order F_minus will be automatically ascending sorted
3561  //to make this sure for foreign gauss
3562  //uncomment the following line
3563  //  qsort(F_minus, F_minus_index,sizeof(poly),pLmCmp_func);
3564  assume((F_plus_index+F_minus_index)==m_index);
3565  if (TEST_OPT_PROT)
3566    Print("%i]", F_plus_index);
3567  for(i=0;i<p_index;i++) 
3568    pDelete(&p[i]);
3569  omfree(p);
3570  p=NULL;
3571  omfree(m);
3572  m=NULL;
3573
3574  //the F_minus list must be cleared separately at the end
3575  mp_array_list** F_i;
3576  poly_array_list** F_m_i;
3577  F_i=&(c->F);
3578  F_m_i=&(c->F_minus);
3579
3580  while((*F_i)!=NULL)
3581  {
3582    assume((*F_m_i)!=NULL);
3583    F_i=(&((*F_i)->next));
3584    F_m_i=(&((*F_m_i)->next));
3585  }
3586  assume((*F_m_i)==NULL);
3587  //should resize the array to save memory
3588  //F and F_minus
3589  qsort(chosen,chosen_index,sizeof(monom_poly),monom_poly_crit);//important for simplify
3590  (*F_m_i)=(poly_array_list*) omalloc(sizeof(poly_array_list));
3591  (*F_m_i)->size=F_minus_index;
3592  (*F_m_i)->p=F_minus;
3593  (*F_m_i)->next=NULL;
3594  (*F_i)=(mp_array_list*) omalloc(sizeof(poly_array_list));
3595  (*F_i)->size=chosen_index;
3596  (*F_i)->mp=chosen;
3597  (*F_i)->next=NULL;
3598 
3599  if(F_plus_index>0)
3600  {
3601    int j;
3602    int* ibuf=(int*) omalloc(F_plus_index*sizeof(int));
3603    sorted_pair_node*** sbuf=(sorted_pair_node***) omalloc(F_plus_index*sizeof(sorted_pair_node**));
3604 
3605    for(j=0;j<F_plus_index;j++)
3606    {
3607      int len;
3608      poly p=F_plus[j];
3609   
3610    // delete buf[j];
3611    //remember to free res here
3612    //    p=redTailShort(p, c->strat);
3613      sbuf[j]=add_to_basis_ideal_quotient(p,-1,-1,c,ibuf+j);
3614   
3615    }
3616    int sum=0;
3617    for(j=0;j<F_plus_index;j++)
3618    {
3619      sum+=ibuf[j];
3620    }
3621    sorted_pair_node** big_sbuf=(sorted_pair_node**) omalloc(sum*sizeof(sorted_pair_node*));
3622    int partsum=0;
3623    for(j=0;j<F_plus_index;j++)
3624    {
3625      memmove(big_sbuf+partsum, sbuf[j],ibuf[j]*sizeof(sorted_pair_node*));
3626      omfree(sbuf[j]);
3627      partsum+=ibuf[j];
3628    }
3629
3630    qsort(big_sbuf,sum,sizeof(sorted_pair_node*),pair_better_gen2);
3631    c->apairs=merge(c->apairs,c->pair_top+1,big_sbuf,sum,c);
3632    c->pair_top+=sum;
3633    clean_top_of_pair_list(c);
3634    omfree(big_sbuf);
3635    omfree(sbuf);
3636    omfree(ibuf);
3637  }
3638  omfree(F_plus);
3639#ifdef TGB_DEBUG
3640  int z;
3641  for(z=1;z<=c->pair_top;z++)
3642  {
3643    assume(pair_better(c->apairs[z],c->apairs[z-1],c));
3644  }
3645#endif
3646
3647  return;
3648}
3649
3650
3651static int poly_crit(const void* ap1, const void* ap2){
3652  poly p1,p2;
3653  p1=*((poly*) ap1);
3654  p2=*((poly*)ap2);
3655
3656  int c=pLmCmp(p1,p2);
3657  if (c !=0) return c;
3658  int l1=pLength(p1);
3659  int l2=pLength(p2);
3660  if (l1<l2) return -1;
3661  if (l1>l2) return 1;
3662  return 0;
3663}
3664
3665ideal t_rep_gb(ring r,ideal arg_I, BOOLEAN F4_mode){
3666  if (TEST_OPT_PROT)
3667    if (F4_mode)
3668      PrintS("F4 Modus \n");
3669   
3670     
3671  //debug_Ideal=arg_debug_Ideal;
3672  //if (debug_Ideal) PrintS("DebugIdeal received\n");
3673  // Print("Idelems %i \n----------\n",IDELEMS(arg_I));
3674  ideal I=idCompactify(arg_I);
3675  qsort(I->m,IDELEMS(I),sizeof(poly),poly_crit);
3676  //Print("Idelems %i \n----------\n",IDELEMS(I));
3677  calc_dat* c=(calc_dat*) omalloc(sizeof(calc_dat));
3678 
3679  c->r=currRing;
3680  c->is_homog=TRUE;
3681  {
3682    int hz;
3683    for(hz=0;hz<IDELEMS(I);hz++){
3684      assume(I->m[hz]!=NULL);
3685      int d=pTotaldegree(I->m[hz]);
3686      poly t=I->m[hz]->next;
3687      while(t)
3688      {
3689        if (d!=pTotaldegree(t,c->r))
3690        {
3691          c->is_homog=FALSE;
3692          break;
3693        }
3694        t=t->next;
3695      }
3696      if(!(c->is_homog)) break;
3697    }
3698  }
3699  //  Print("is homog:%d",c->is_homog);
3700  void* h;
3701  poly hp;
3702  int i,j;
3703  c->to_destroy=NULL;
3704  c->easy_product_crit=0;
3705  c->extended_product_crit=0;
3706  c->is_char0=(rChar()==0);
3707  c->F4_mode=F4_mode;
3708  c->reduction_steps=0;
3709  c->last_index=-1;
3710
3711  c->F=NULL;
3712  c->F_minus=NULL;
3713
3714  c->Rcounter=0;
3715
3716  c->soon_free=NULL;
3717
3718  c->tmp_lm=pOne();
3719
3720  c->normal_forms=0;
3721  c->current_degree=1;
3722 
3723  c->max_pairs=5*I->idelems();
3724 
3725  c->apairs=(sorted_pair_node**) omalloc(sizeof(sorted_pair_node*)*c->max_pairs);
3726  c->pair_top=-1;
3727
3728  int n=I->idelems();
3729  if (TEST_OPT_PROT)
3730    for (i=0;i<n;i++){
3731      wrp(I->m[i]);
3732      PrintS("\n");
3733    }
3734  i=0;
3735  c->n=0;
3736  c->T_deg=(int*) omalloc(n*sizeof(int));
3737  c->tmp_pair_lm=(poly*) omalloc(n*sizeof(poly));
3738  lm_bin=omGetSpecBin(POLYSIZE + (r->ExpL_Size)*sizeof(long));
3739#ifdef HEAD_BIN
3740  c->HeadBin=omGetSpecBin(POLYSIZE + (currRing->ExpL_Size)*sizeof(long));
3741#endif
3742  /* omUnGetSpecBin(&(c->HeadBin)); */
3743  h=omalloc(n*sizeof(char*));
3744  c->states=(char**) h;
3745  h=omalloc(n*sizeof(int));
3746  c->lengths=(int*) h;
3747  h=omalloc(n*sizeof(int));
3748        c->gcd_of_terms=(poly*) omalloc(n*sizeof(poly));
3749  c->rep=(int*) h;
3750  c->short_Exps=(long*) omalloc(n*sizeof(long));
3751  c->S=idInit(n,1);
3752  c->strat=new skStrategy;
3753  c->strat->syzComp = 0;
3754  initBuchMoraCrit(c->strat);
3755  initBuchMoraPos(c->strat);
3756  c->strat->initEcart = initEcartBBA;
3757  c->strat->enterS = enterSBba;
3758  c->strat->sl = -1;
3759  i=n;
3760  /* initS(c->S,NULL,c->strat); */
3761/* intS start: */
3762  i=((i+IDELEMS(c->S)+15)/16)*16;
3763  c->strat->ecartS=(intset)omAlloc(i*sizeof(int)); /*initec(i);*/
3764  c->strat->sevS=(unsigned long*)omAlloc0(i*sizeof(unsigned long));
3765  /*initsevS(i);*/
3766  c->strat->S_2_R=(int*)omAlloc0(i*sizeof(int));/*initS_2_R(i);*/
3767  c->strat->fromQ=NULL;
3768  c->strat->Shdl=idInit(1,1);
3769  c->strat->S=c->strat->Shdl->m;
3770  c->strat->lenS=(int*)omAlloc0(i*sizeof(int));
3771  if(c->is_char0)
3772    c->strat->lenSw=(int*)omAlloc0(i*sizeof(int));
3773  else
3774    c->strat->lenSw=NULL;
3775  sorted_pair_node* si;
3776  assume(n>0);
3777  add_to_basis(I->m[0],-1,-1,c);
3778
3779  assume(c->strat->sl==c->strat->Shdl->idelems()-1);
3780  if(!(F4_mode))
3781  {
3782    for (i=1;i<n;i++)//the 1 is wanted, because first element is added to basis
3783    {
3784      //     add_to_basis(I->m[i],-1,-1,c);
3785      si=(sorted_pair_node*) omalloc(sizeof(sorted_pair_node));
3786      si->i=-1;
3787      si->j=-1;
3788      si->expected_length=pLength(I->m[i]);
3789      si->deg=pTotaldegree(I->m[i]);
3790      if (!rField_is_Zp(c->r)){ 
3791        pCleardenom(I->m[i]);
3792      }
3793      si->lcm_of_lm=I->m[i];
3794     
3795      //      c->apairs[n-1-i]=si;
3796      c->apairs[n-i-1]=si;
3797      ++(c->pair_top);
3798    }
3799  }
3800  else
3801  {
3802     for (i=1;i<n;i++)//the 1 is wanted, because first element is added to basis
3803       add_to_basis(I->m[i],-1,-1,c);
3804  }
3805   
3806
3807  while(c->pair_top>=0)
3808  {
3809    if(F4_mode)
3810      go_on_F4(c);
3811    else
3812      go_on(c);
3813  }
3814  while(c->to_destroy)
3815  {
3816    pDelete(&(c->to_destroy->p));
3817    poly_list_node* old=c->to_destroy;
3818    c->to_destroy=c->to_destroy->next;
3819    omfree(old);
3820  }
3821  while(c->F)
3822  {
3823    for(i=0;i<c->F->size;i++){
3824      pDelete(&(c->F->mp[i].m));
3825    }
3826    omfree(c->F->mp);
3827    c->F->mp=NULL;
3828    mp_array_list* old=c->F;
3829    c->F=c->F->next;
3830    omfree(old);
3831  }
3832  while(c->F_minus)
3833  {
3834    for(i=0;i<c->F_minus->size;i++){
3835      pDelete(&(c->F_minus->p[i]));
3836    }
3837    omfree(c->F_minus->p);
3838    c->F_minus->p=NULL;
3839    poly_array_list* old=c->F_minus;
3840    c->F_minus=c->F_minus->next;
3841    omfree(old);
3842  }
3843  for(int z=0;z<c->n;z++){
3844    omfree(c->states[z]);
3845  }
3846  omfree(c->states);
3847  omfree(c->lengths);
3848  for(int z=0;z<c->n;z++)
3849  {
3850    pDelete(&c->tmp_pair_lm[z]);
3851  }
3852  omfree(c->tmp_pair_lm);
3853
3854  omfree(c->short_Exps);
3855  omfree(c->T_deg);
3856
3857     omFree(c->strat->ecartS);
3858     omFree(c->strat->sevS);
3859//   initsevS(i);
3860   omFree(c->strat->S_2_R);
3861   
3862
3863  omFree(c->strat->lenS);
3864
3865   if(c->strat->lenSw)  omFree(c->strat->lenSw);
3866
3867
3868
3869
3870  for(i=0;i<c->n;i++){
3871    if(c->gcd_of_terms[i])
3872      pDelete(&(c->gcd_of_terms[i]));
3873  }
3874  omfree(c->gcd_of_terms);
3875
3876  omfree(c->apairs);
3877  if (TEST_OPT_PROT)
3878  {
3879    Print("calculated %d NFs\n",c->normal_forms);
3880    Print("applied %i product crit, %i extended_product crit \n", c->easy_product_crit, c->extended_product_crit);
3881  }
3882  int deleted_form_c_s=0;
3883 
3884  for(i=0;i<=c->strat->sl;i++){
3885    if (!c->strat->S[i]) continue;
3886    BOOLEAN found=FALSE;
3887    for(j=0;j<c->n;j++){
3888      if (c->S->m[j]==c->strat->S[i]){
3889        found=TRUE;
3890        break;
3891      }
3892    }
3893    if(!found) pDelete(&c->strat->S[i]);
3894  }
3895//   for(i=0;i<c->n;i++){
3896//     if (c->rep[i]!=i){
3897// //       for(j=0;j<=c->strat->sl;j++){
3898// //   if(c->strat->S[j]==c->S->m[i]){
3899// //     c->strat->S[j]=NULL;
3900// //     break;
3901// //   }
3902// //       }
3903// //      PrintS("R_delete");
3904//       pDelete(&c->S->m[i]);
3905//     }
3906//   }
3907
3908//  qsort(c->S->m, c->n,sizeof(poly),pLmCmp_func);
3909  for(i=0;i<c->n;i++)
3910  {
3911    assume(c->S->m[i]!=NULL);
3912    for(j=0;j<c->n;j++)
3913    {
3914      if((c->S->m[j]==NULL)||(i==j)) 
3915        continue;
3916      assume(p_LmShortDivisibleBy(c->S->m[j],c->short_Exps[j],
3917                               c->S->m[i],~c->short_Exps[i],
3918                                   c->r)==p_LmDivisibleBy(c->S->m[j],
3919                                                        c->S->m[i],
3920                                                          c->r));
3921      if (p_LmShortDivisibleBy(c->S->m[j],c->short_Exps[j],
3922                               c->S->m[i],~c->short_Exps[i],
3923                                   c->r))
3924      {
3925        pDelete(&c->S->m[i]);
3926        break;
3927      }
3928    }
3929  }
3930  omfree(c->rep);
3931  for(i=0;i<I->idelems();i++)
3932  {
3933    I->m[i]=NULL;
3934  }
3935  idDelete(&I);
3936  I=c->S;
3937 
3938  IDELEMS(I)=c->n;
3939
3940  idSkipZeroes(c->S);
3941  for(i=0;i<=c->strat->sl;i++)
3942    c->strat->S[i]=NULL;
3943  id_Delete(&c->strat->Shdl,c->r);
3944  pDelete(&c->tmp_lm);
3945  omUnGetSpecBin(&lm_bin);
3946  delete c->strat;
3947  omfree(c);
3948
3949  return(I);
3950}
3951static void now_t_rep(const int & arg_i, const int & arg_j, calc_dat* c){
3952  int i,j;
3953  if (arg_i==arg_j){
3954    return;
3955  }
3956  if (arg_i>arg_j){
3957    i=arg_j;
3958    j=arg_i;
3959  } else {
3960    i=arg_i;
3961    j=arg_j;
3962  }
3963  c->states[j][i]=HASTREP;
3964}
3965static void soon_t_rep(const int& arg_i, const int& arg_j, calc_dat* c)
3966{
3967  assume(0<=arg_i);
3968  assume(0<=arg_j);
3969  assume(arg_i<c->n);
3970  assume(arg_j<c->n);
3971  int i,j;
3972  if (arg_i==arg_j){
3973    return;
3974  }
3975  if (arg_i>arg_j){
3976    i=arg_j;
3977    j=arg_i;
3978  } else {
3979    i=arg_i;
3980    j=arg_j;
3981  }
3982  if (!
3983      (c->states[j][i]==HASTREP))
3984    c->states[j][i]=SOONTREP;
3985}
3986static BOOLEAN has_t_rep(const int & arg_i, const  int & arg_j, calc_dat* state){
3987  assume(0<=arg_i);
3988  assume(0<=arg_j);
3989  assume(arg_i<state->n);
3990  assume(arg_j<state->n);
3991  if (arg_i==arg_j)
3992  {
3993    return (TRUE);
3994  }
3995  if (arg_i>arg_j)
3996  {
3997    return (state->states[arg_i][arg_j]==HASTREP);
3998  } else
3999  {
4000    return (state->states[arg_j][arg_i]==HASTREP);
4001  }
4002}
4003static int pLcmDeg(poly a, poly b)
4004{
4005  int i;
4006  int n=0;
4007  for (i=pVariables; i; i--)
4008  {
4009    n+=max( pGetExp(a,i), pGetExp(b,i));
4010  }
4011  return n;
4012
4013}
4014
4015
4016
4017static void shorten_tails(calc_dat* c, poly monom)
4018{
4019  return;
4020// BOOLEAN corr=lenS_correct(c->strat);
4021  for(int i=0;i<c->n;i++)
4022  {
4023    //enter tail
4024    if (c->rep[i]!=i) continue;
4025    if (c->S->m[i]==NULL) continue;
4026    poly tail=c->S->m[i]->next;
4027    poly prev=c->S->m[i];
4028    BOOLEAN did_something=FALSE;
4029    while((tail!=NULL)&& (pLmCmp(tail, monom)>=0))
4030    {
4031      if (p_LmDivisibleBy(monom,tail,c->r))
4032      {
4033        did_something=TRUE;
4034        prev->next=tail->next;
4035        tail->next=NULL;
4036        p_Delete(& tail,c->r);
4037        tail=prev;
4038        //PrintS("Shortened");
4039        c->lengths[i]--;
4040      }
4041      prev=tail;
4042      tail=tail->next;
4043    }
4044    if (did_something)
4045    {
4046      int new_pos;
4047      int q;
4048      q=quality(c->S->m[i],c->lengths[i],c);
4049      new_pos=simple_posInS(c->strat,c->S->m[i],q,c->is_char0);
4050
4051      int old_pos=-1;
4052      //assume new_pos<old_pos
4053      for (int z=0;z<=c->strat->sl;z++)
4054      {
4055        if (c->strat->S[z]==c->S->m[i])
4056        {
4057          old_pos=z;
4058          break;
4059        }
4060      }
4061      if (old_pos== -1)
4062        for (int z=new_pos-1;z>=0;z--)
4063        {
4064          if (c->strat->S[z]==c->S->m[i])
4065          {
4066            old_pos=z;
4067            break;
4068          }
4069        }
4070      assume(old_pos>=0);
4071      assume(new_pos<=old_pos);
4072      assume(pLength(c->strat->S[old_pos])==c->lengths[i]);
4073      c->strat->lenS[old_pos]=c->lengths[i];
4074      if (c->strat->lenSw)
4075        c->strat->lenSw[old_pos]=q;
4076
4077      if (new_pos<old_pos)
4078        move_forward_in_S(old_pos,new_pos,c->strat, c->is_char0);
4079
4080      length_one_crit(c,i,c->lengths[i]);
4081    }
4082  }
4083}
4084static sorted_pair_node* pop_pair(calc_dat* c){
4085  clean_top_of_pair_list(c);
4086
4087  if(c->pair_top<0) return NULL;
4088  else return (c->apairs[c->pair_top--]);
4089}
4090static sorted_pair_node* top_pair(calc_dat* c){
4091  super_clean_top_of_pair_list(c);//yeah, I know, it's odd that I use a different proc here
4092
4093  if(c->pair_top<0) return NULL;
4094  else return (c->apairs[c->pair_top]);
4095}
4096static sorted_pair_node* quick_pop_pair(calc_dat* c){
4097  if(c->pair_top<0) return NULL;
4098  else return (c->apairs[c->pair_top--]);
4099}
4100static BOOLEAN no_pairs(calc_dat* c){
4101  clean_top_of_pair_list(c);
4102  return (c->pair_top==-1);
4103}
4104
4105
4106static void super_clean_top_of_pair_list(calc_dat* c){
4107  while((c->pair_top>=0)
4108  && (c->apairs[c->pair_top]->i>=0)
4109  && (good_has_t_rep(c->apairs[c->pair_top]->j, c->apairs[c->pair_top]->i,c)))
4110  {
4111
4112    free_sorted_pair_node(c->apairs[c->pair_top],c->r);
4113    c->pair_top--;
4114
4115  }
4116}
4117static void clean_top_of_pair_list(calc_dat* c){
4118  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))){
4119
4120    free_sorted_pair_node(c->apairs[c->pair_top],c->r);
4121    c->pair_top--;
4122
4123  }
4124}
4125static BOOLEAN state_is(calc_state state, const int & arg_i, const  int & arg_j, calc_dat* c){
4126  assume(0<=arg_i);
4127  assume(0<=arg_j);
4128  assume(arg_i<c->n);
4129  assume(arg_j<c->n);
4130  if (arg_i==arg_j)
4131  {
4132    return (TRUE);
4133  }
4134  if (arg_i>arg_j)
4135  {
4136    return (c->states[arg_i][arg_j]==state);
4137  }
4138  else return(c->states[arg_j][arg_i]==state);
4139}
4140static void free_sorted_pair_node(sorted_pair_node* s, ring r){
4141  if (s->i>=0)
4142    p_Delete(&s->lcm_of_lm,r);
4143  omfree(s);
4144}
4145static BOOLEAN pair_better(sorted_pair_node* a,sorted_pair_node* b, calc_dat* c){
4146  if (a->deg<b->deg) return TRUE;
4147  if (a->deg>b->deg) return FALSE;
4148
4149//  if (a->expected_length<b->expected_length) return TRUE;
4150  //  if (a->expected_length>b->expected_length) return FALSE;
4151  int comp=pLmCmp(a->lcm_of_lm, b->lcm_of_lm);
4152  if (comp==1) return FALSE;
4153  if (-1==comp) return TRUE;
4154  if (a->i+a->j<b->i+b->j) return TRUE;
4155   if (a->i+a->j>b->i+b->j) return FALSE;
4156  if (a->i<b->i) return TRUE;
4157  if (a->i>b->i) return FALSE;
4158  return TRUE;
4159}
4160
4161static int pair_better_gen(const void* ap,const void* bp){
4162
4163  sorted_pair_node* a=*((sorted_pair_node**)ap);
4164  sorted_pair_node* b=*((sorted_pair_node**)bp);
4165  assume(a->i>a->j);
4166  assume(b->i>b->j);
4167  if (a->deg<b->deg) return -1;
4168  if (a->deg>b->deg) return 1;
4169
4170
4171//  if (a->expected_length<b->expected_length) return -1;
4172  // if (a->expected_length>b->expected_length) return 1;
4173 int comp=pLmCmp(a->lcm_of_lm, b->lcm_of_lm);
4174 
4175  if (comp==1) return 1;
4176  if (-1==comp) return -1;
4177  if (a->i+a->j<b->i+b->j) return -1;
4178   if (a->i+a->j>b->i+b->j) return 1;
4179  if (a->i<b->i) return -1;
4180   if (a->i>b->i) return 1;
4181  return 0;
4182}
4183
4184
4185static poly gcd_of_terms(poly p, ring r){
4186  int max_g_0=0;
4187  assume(p!=NULL);
4188  int i;
4189  poly m=pOne();
4190  poly t;
4191  for (i=pVariables; i; i--)
4192  {
4193      pSetExp(m,i, pGetExp(p,i));
4194      if (max_g_0==0)
4195        if (pGetExp(m,i)>0)
4196          max_g_0=i;
4197  }
4198 
4199  t=p->next;
4200  while (t!=NULL){
4201   
4202    if (max_g_0==0) break;
4203    for (i=max_g_0; i; i--)
4204    {
4205      pSetExp(m,i, min(pGetExp(t,i),pGetExp(m,i)));
4206      if (max_g_0==i)
4207        if (pGetExp(m,i)==0)
4208          max_g_0=0;
4209      if ((max_g_0==0) && (pGetExp(m,i)>0)){
4210        max_g_0=i;
4211      }
4212    }
4213    t=t->next;
4214  }
4215  // for (i=pVariables;i;i--)
4216//   {
4217//     if(pGetExp(m,i)>0)
4218//       return m;
4219//   }
4220  if (max_g_0>0)
4221    return m;
4222  pDelete(&m);
4223  return NULL;
4224}
4225static inline BOOLEAN pHasNotCFExtended(poly p1, poly p2, poly m)
4226{
4227
4228  if (pGetComp(p1) > 0 || pGetComp(p2) > 0)
4229    return FALSE;
4230  int i = 1;
4231  loop
4232  {
4233    if ((pGetExp(p1, i)-pGetExp(m,i) >0) && (pGetExp(p2, i) -pGetExp(m,i)> 0))   return FALSE;
4234    if (i == pVariables)                                return TRUE;
4235    i++;
4236  }
4237}
4238
4239
4240//for impl reasons may return false if the the normal product criterion matches
4241static inline BOOLEAN extended_product_criterion(poly p1, poly gcd1, poly p2, poly gcd2, calc_dat* c){
4242  if(gcd1==NULL) return FALSE;
4243        if(gcd2==NULL) return FALSE;
4244        gcd1->next=gcd2; //may ordered incorrect
4245        poly m=gcd_of_terms(gcd1,c->r);
4246        gcd1->next=NULL;
4247        if (m==NULL) return FALSE;
4248
4249        BOOLEAN erg=pHasNotCFExtended(p1,p2,m);
4250        pDelete(&m);
4251        return erg;
4252}
4253static poly kBucketGcd(kBucket* b, ring r)
4254{
4255  int s=0;
4256  int i;
4257  poly m, n;
4258  BOOLEAN initialized=FALSE;
4259  for (i=MAX_BUCKET-1;i>=0;i--)
4260  { 
4261    if (b->buckets[i]!=NULL){
4262      if (!initialized){
4263        m=gcd_of_terms(b->buckets[i],r);
4264        initialized=TRUE;
4265        if (m==NULL) return NULL;
4266      }
4267      else
4268        {
4269          n=gcd_of_terms(b->buckets[i],r);
4270          if (n==NULL) {
4271            pDelete(&m);
4272            return NULL;   
4273          }
4274          n->next=m;
4275          poly t=gcd_of_terms(n,r);
4276          n->next=NULL;
4277          pDelete(&m);
4278          pDelete(&n);
4279          m=t;
4280          if (m==NULL) return NULL;
4281         
4282        }
4283    }
4284  }
4285  return m;
4286}
4287
4288
4289
4290static int guess_quality(const red_object & p, calc_dat* c){
4291  //looks only on bucket
4292  if (c->is_char0) return kSBucketLength(p.bucket);
4293  return (bucket_guess(p.bucket));
4294}
4295static int quality_of_pos_in_strat_S(int pos, calc_dat* c){
4296  if (c->is_char0) return c->strat->lenSw[pos];
4297  return c->strat->lenS[pos];
4298}
4299static int quality(poly p, int len, calc_dat* c){
4300  if (c->is_char0) return pSLength(p,len);
4301  return pLength(p);
4302}
4303static void multi_reduction_lls_trick(red_object* los, int losl,calc_dat* c,find_erg & erg){
4304  erg.expand=NULL;
4305  BOOLEAN swap_roles; //from reduce_by, to_reduce_u if fromS
4306  if(erg.fromS){
4307    if(pLmEqual(c->strat->S[erg.reduce_by],los[erg.to_reduce_u].p))
4308    {
4309      int i;
4310      int quality_a=quality_of_pos_in_strat_S(erg.reduce_by,c);
4311      int best=erg.to_reduce_u+1;
4312/*
4313      for (i=erg.to_reduce_u;i>=erg.to_reduce_l;i--){
4314        int qc=los[i].guess_quality(c);
4315        if (qc<quality_a){
4316          best=i;
4317          quality_a=qc;
4318        }
4319      }
4320      if(best!=erg.to_reduce_u+1){*/
4321      int qc;
4322      best=find_best(los,erg.to_reduce_l,erg.to_reduce_u,qc,c);
4323      assume(qc==los[best].guess_quality(c));
4324      if(qc<quality_a){
4325        red_object h=los[erg.to_reduce_u];
4326        los[erg.to_reduce_u]=los[best];
4327        los[best]=h;
4328        swap_roles=TRUE;
4329      }
4330      else{
4331       
4332        swap_roles=FALSE;
4333      }
4334 
4335    }
4336      else
4337    {
4338      if (erg.to_reduce_u>erg.to_reduce_l){
4339
4340        int i;
4341        int quality_a=quality_of_pos_in_strat_S(erg.reduce_by,c);
4342        int best=erg.to_reduce_u+1;
4343        int qc;
4344        best=find_best(los,erg.to_reduce_l,erg.to_reduce_u,qc,c);
4345        assume(qc==los[best].guess_quality(c));
4346        if(qc<quality_a){
4347          //(best!=erg.to_reduce_u+1){
4348          red_object h=los[erg.to_reduce_l];
4349          los[erg.to_reduce_l]=los[best];
4350          los[best]=h;
4351          erg.reduce_by=erg.to_reduce_l;
4352          erg.fromS=FALSE;
4353          erg.to_reduce_l++;
4354         
4355        }
4356      }
4357      else 
4358      {
4359        assume(erg.to_reduce_u==erg.to_reduce_l);
4360        int quality_a=quality_of_pos_in_strat_S(erg.reduce_by,c);
4361        int qc=los[erg.to_reduce_u].guess_quality(c);
4362        if(qc<quality_a){
4363          BOOLEAN exp=FALSE;
4364          if(qc<=2)
4365            exp=TRUE;
4366          else {
4367            if (qc<quality_a/2)
4368              exp=TRUE;
4369            else
4370              if(erg.reduce_by<c->n/4)
4371                exp=TRUE;
4372          }
4373          if (exp){
4374            poly clear_into;
4375            los[erg.to_reduce_u].flatten();
4376            kBucketClear(los[erg.to_reduce_u].bucket,&clear_into,&erg.expand_length);
4377            erg.expand=pCopy(clear_into);
4378            kBucketInit(los[erg.to_reduce_u].bucket,clear_into,erg.expand_length);
4379            if (TEST_OPT_PROT)
4380              PrintS("e");
4381           
4382          }
4383        }
4384
4385       
4386      }
4387     
4388      swap_roles=FALSE;
4389      return;
4390      }
4391   
4392  }
4393  else{
4394    if(erg.reduce_by>erg.to_reduce_u){
4395      //then lm(rb)>= lm(tru) so =
4396      assume(erg.reduce_by==erg.to_reduce_u+1);
4397      int best=erg.reduce_by;
4398      int quality_a=los[erg.reduce_by].guess_quality(c);
4399      int qc;
4400      best=find_best(los,erg.to_reduce_l,erg.to_reduce_u,qc,c);
4401     
4402      int i;
4403      if(qc<quality_a){
4404          red_object h=los[erg.reduce_by];
4405          los[erg.reduce_by]=los[best];
4406          los[best]=h;
4407        }
4408        swap_roles=FALSE;
4409        return;
4410       
4411         
4412    }
4413    else
4414    {
4415      assume(!pLmEqual(los[erg.reduce_by].p,los[erg.to_reduce_l].p));
4416      //further assume, that reduce_by is the above all other polys
4417      //with same leading term
4418      int il=erg.reduce_by;
4419      int quality_a =los[erg.reduce_by].guess_quality(c);
4420      int qc;
4421      while((il>0) && pLmEqual(los[il-1].p,los[il].p)){
4422        il--;
4423        qc=los[il].guess_quality(c);
4424        if (qc<quality_a){
4425          quality_a=qc;
4426          erg.reduce_by=il;
4427        }
4428      }
4429      swap_roles=FALSE;
4430    }
4431 
4432  }
4433  if(swap_roles)
4434  {
4435    if (TEST_OPT_PROT)
4436      PrintS("b");
4437    poly clear_into;
4438    int dummy_len;
4439    int new_length;
4440    int bp=erg.to_reduce_u;//bucket_positon
4441    //kBucketClear(los[bp].bucket,&clear_into,&new_length);
4442    new_length=los[bp].clear_to_poly();
4443    clear_into=los[bp].p;
4444    poly p=c->strat->S[erg.reduce_by];
4445    int j=erg.reduce_by;
4446    int old_length=c->strat->lenS[j];// in view of S
4447    los[bp].p=p;
4448    kBucketInit(los[bp].bucket,p,old_length);
4449    int qal=quality(clear_into,new_length,c);
4450    int pos_in_c=-1;   
4451    int z;
4452    int new_pos;
4453    new_pos=simple_posInS(c->strat,clear_into,qal,c->is_char0);
4454    assume(new_pos<=j);
4455    for (z=c->n;z;z--)
4456    {
4457      if(p==c->S->m[z-1])
4458      {
4459        pos_in_c=z-1;
4460        break;
4461      }
4462    }
4463    if(pos_in_c>=0)
4464    {
4465      c->S->m[pos_in_c]=clear_into;
4466      c->lengths[pos_in_c]=new_length;
4467      c_S_element_changed_hook(pos_in_c,c);
4468    }
4469    c->strat->S[j]=clear_into;
4470    c->strat->lenS[j]=new_length;
4471    if(c->strat->lenSw)
4472      c->strat->lenS[j]=qal;
4473    if (!rField_is_Zp(c->r))
4474    {
4475      pContent(clear_into);
4476      pCleardenom(clear_into);//should be unnecessary
4477    }
4478    else                     
4479      pNorm(clear_into);
4480#ifdef FIND_DETERMINISTIC
4481    erg.reduce_by=j;
4482    //resort later see diploma thesis, find_in_S must be deterministic
4483    //during multireduction if spolys are only in the span of the
4484    //input polys
4485#else
4486   
4487    if (new_pos<j)
4488    { 
4489      move_forward_in_S(j,new_pos,c->strat,c->is_char0);
4490      erg.reduce_by=new_pos;
4491    }
4492#endif
4493  }
4494}
4495static int fwbw(red_object* los, int i){
4496   int i2=i;
4497   int step=1;
4498   
4499   BOOLEAN bw=FALSE;
4500   BOOLEAN incr=TRUE;
4501   
4502   while(1)
4503   {
4504     if(!bw)
4505     {
4506       step=min(i2,step);
4507       if (step==0) break;
4508       i2-=step;
4509         
4510       if(!pLmEqual(los[i].p,los[i2].p))
4511       {
4512         bw=TRUE;
4513         incr=FALSE;
4514       }
4515       else
4516       {
4517         if ((!incr) &&(step==1)) break;
4518       }
4519       
4520       
4521     }
4522     else
4523     {
4524       
4525       step=min(i-i2,step);
4526       if (step==0) break;
4527       i2+=step;
4528       if(pLmEqual(los[i].p,los[i2].p)){
4529         if(step==1) break;
4530         else
4531         {
4532           bw=FALSE;
4533         }
4534       }
4535       
4536     }
4537     if (incr)
4538       step*=2;
4539     else
4540     {
4541       if (step%2==1)
4542         step=(step+1)/2;
4543       else
4544         step/=2;
4545       
4546     }
4547   }
4548   return i2;
4549}
4550static void multi_reduction_find(red_object* los, int losl,calc_dat* c,int startf,find_erg & erg){
4551  kStrategy strat=c->strat;
4552
4553  assume(startf<=losl);
4554  assume((startf==losl-1)||(pLmCmp(los[startf].p,los[startf+1].p)==-1));
4555  int i=startf;
4556 
4557  int j;
4558  while(i>=0){
4559    assume((i==losl-1)||(pLmCmp(los[i].p,los[i+1].p)<=0));
4560    assume(is_valid_ro(los[i]));
4561    j=kFindDivisibleByInS_easy(strat,los[i]);
4562    if(j>=0){
4563     
4564      erg.to_reduce_u=i;
4565      erg.reduce_by=j;
4566      erg.fromS=TRUE;
4567      int i2=fwbw(los,i);
4568      assume(pLmEqual(los[i].p,los[i2].p));
4569      assume((i2==0)||(!pLmEqual(los[i2].p,los[i2-1].p)));
4570      assume(i>=i2);
4571
4572//       int i2;
4573//       for(i2=i-1;i2>=0;i2--){
4574//      if(!pLmEqual(los[i].p,los[i2].p))
4575//        break;
4576//      }
4577     
4578//      erg.to_reduce_l=i2+1;
4579      erg.to_reduce_l=i2;
4580      assume((i==losl-1)||(pLmCmp(los[i].p,los[i+1].p)==-1));
4581      return;
4582    }
4583    if (j<0){
4584     
4585      //not reduceable, try to use this for reducing higher terms
4586      int i2=fwbw(los,i);
4587      assume(pLmEqual(los[i].p,los[i2].p));
4588      assume((i2==0)||(!pLmEqual(los[i2].p,los[i2-1].p)));
4589      assume(i>=i2);
4590      if(i2!=i){
4591       
4592        erg.to_reduce_u=i-1;
4593        erg.to_reduce_l=i2;
4594        erg.reduce_by=i;
4595        erg.fromS=FALSE;
4596        assume((i==losl-1)||(pLmCmp(los[i].p,los[i+1].p)==-1));
4597        return;
4598      }
4599      if(!(c->is_homog))
4600      {
4601
4602        for (i2=i+1;i2<losl;i2++){
4603          if (p_LmShortDivisibleBy(los[i].p,los[i].sev,los[i2].p,~los[i2].sev,
4604                                   c->r)){
4605            int i3=i2;
4606            while((i3+1<losl) && (pLmEqual(los[i2].p, los[i3+1].p)))
4607              i3++;
4608            erg.to_reduce_u=i3;
4609            erg.to_reduce_l=i2;
4610            erg.reduce_by=i;
4611            erg.fromS=FALSE;
4612            assume((i==losl-1)||(pLmCmp(los[i].p,los[i+1].p)==-1));
4613            return;
4614          }
4615          //    else {assume(!p_LmDivisibleBy(los[i].p, los[i2].p,c->r));}
4616        }
4617      }
4618      i--;
4619    }
4620  }
4621  erg.reduce_by=-1;//error code
4622  return;
4623}
4624
4625 //  nicht reduzierbare eintraege in ergebnisliste schreiben
4626//   nullen loeschen
4627//   while(finde_groessten leitterm reduzierbar(c,erg)){
4628 
4629static int multi_reduction_clear_zeroes(red_object* los, int  losl, int l, int u)
4630{
4631
4632
4633  int deleted=0;
4634  int  i=l;
4635  int last=-1;
4636  while(i<=u)
4637  {
4638   
4639    if(los[i].p==NULL){
4640      kBucketDestroy(&los[i].bucket);
4641//      delete los[i];//here we assume los are constructed with new
4642      //destroy resources, must be added here   
4643     if (last>=0)
4644     {
4645       memmove(los+(int)(last+1-deleted),los+(last+1),sizeof(red_object)*(i-1-last));
4646     }
4647     last=i;
4648     deleted++;
4649    }
4650    i++;
4651  }
4652  if((last>=0)&&(last!=losl-1))
4653      memmove(los+(int)(last+1-deleted),los+last+1,sizeof(red_object)*(losl-1-last));
4654  return deleted;
4655 
4656}
4657
4658static void sort_region_down(red_object* los, int l, int u, calc_dat* c)
4659{
4660  qsort(los+l,u-l+1,sizeof(red_object),red_object_better_gen);
4661  int i;
4662
4663  for(i=l;i<=u;i++)
4664  {
4665    BOOLEAN moved=FALSE;
4666    int j;
4667    for(j=i;j;j--)
4668    {
4669      if(pLmCmp(los[j].p,los[j-1].p)==-1){
4670        red_object h=los[j];
4671        los[j]=los[j-1];
4672        los[j-1]=h;
4673        moved=TRUE;
4674      }
4675      else break;
4676    }
4677    if(!moved) return;
4678  }
4679}
4680
4681//assume that los is ordered ascending by leading term, all non zero
4682static void multi_reduction(red_object* los, int & losl, calc_dat* c)
4683{
4684 
4685  //initialize;
4686  assume(c->strat->sl>=0);
4687  assume(losl>0);
4688  int i;
4689  for(i=0;i<losl;i++){
4690    los[i].sev=pGetShortExpVector(los[i].p);
4691//SetShortExpVector();
4692    los[i].p=kBucketGetLm(los[i].bucket);
4693  }
4694
4695  kStrategy strat=c->strat;
4696  int curr_pos=losl-1;
4697
4698
4699//  nicht reduzierbare einträge in ergebnisliste schreiben
4700  // nullen loeschen
4701  while(curr_pos>=0){
4702   
4703    find_erg erg;
4704    multi_reduction_find(los, losl,c,curr_pos,erg);//last argument should be curr_pos
4705   //  PrintS("\n erg:\n");
4706//     Print("upper:%i\n",erg.to_reduce_u);
4707//     Print("lower:%i\n",erg.to_reduce_l);
4708//     Print("reduce_by:%i\n",erg.reduce_by);
4709//     Print("fromS:%i\n",erg.fromS);
4710    if(erg.reduce_by<0) break;
4711
4712
4713
4714    erg.expand=NULL;
4715    int d=erg.to_reduce_u-erg.to_reduce_l+1;
4716    //if ((!erg.fromS)&&(d>100)){
4717    if (0){
4718      PrintS("L");
4719      if(!erg.fromS){
4720        erg.to_reduce_u=max(erg.to_reduce_u,erg.reduce_by);
4721        if (pLmEqual(los[erg.reduce_by].p,los[erg.to_reduce_l].p))
4722          erg.to_reduce_l=min(erg.to_reduce_l,erg.reduce_by);
4723      }
4724      int pn=erg.to_reduce_u+1-erg.to_reduce_l;
4725      poly* p=(poly*) omalloc((pn)*sizeof(poly));
4726      int i;
4727      for(i=0;i<pn;i++){
4728        int len;
4729        los[erg.to_reduce_l+i].flatten();
4730        kBucketClear(los[erg.to_reduce_l+i].bucket,&p[i],&len);
4731       
4732        redTailShort(p[i],c->strat);
4733      }
4734      pre_comp(p,pn,c);
4735      int j;
4736      for(j=0;j<pn;j++){
4737        los[erg.to_reduce_l+j].p=p[j];
4738        los[erg.to_reduce_l+j].sev=pGetShortExpVector(p[j]);
4739        los[erg.to_reduce_l+j].sum=NULL;
4740        int len=pLength(p[j]);
4741        kBucketInit(los[erg.to_reduce_l+j].bucket,los[erg.to_reduce_l+j].p,len);
4742      }
4743      for(j=erg.to_reduce_l+pn;j<=erg.to_reduce_u;j++){
4744        los[j].p=NULL;
4745       
4746      }
4747
4748      omfree(p);
4749    }
4750    else {
4751    multi_reduction_lls_trick(los,losl,c,erg);
4752    int sum=0;
4753
4754   
4755    int i;
4756    int len;
4757   
4758    multi_reduce_step(erg,los,c);
4759    }
4760//     reduction_step *rs=create_reduction_step(erg, los, c);
4761//     rs->reduce(los,erg.to_reduce_l,erg.to_reduce_u);
4762//     finalize_reduction_step(rs);
4763                 
4764    int deleted=multi_reduction_clear_zeroes(los, losl, erg.to_reduce_l, erg.to_reduce_u);
4765    if(erg.fromS==FALSE)
4766      curr_pos=max(erg.to_reduce_u,erg.reduce_by);
4767    else
4768      curr_pos=erg.to_reduce_u;
4769    losl -= deleted;
4770    curr_pos -= deleted;
4771
4772    //Print("deleted %i \n",deleted);
4773    sort_region_down(los, erg.to_reduce_l, erg.to_reduce_u-deleted, c);
4774//   sort_region_down(los, 0, losl-1, c);
4775    //  qsort(los,losl,sizeof(red_object),red_object_better_gen);
4776    if(erg.expand)
4777    {
4778#ifdef FIND_DETERMINISTIC
4779      int i;
4780      for(i=0;c->expandS[i];i++);
4781      c->expandS=(poly*) omrealloc(c->expandS,(i+2)*sizeof(poly));
4782      c->expandS[i]=erg.expand;
4783      c->expandS[i+1]=NULL;
4784#else
4785      add_to_reductors(c,erg.expand,erg.expand_length);
4786#endif
4787    }
4788     
4789  }
4790  return;
4791}
4792void red_object::flatten(){
4793  if (sum!=NULL)
4794  {
4795
4796 
4797    if(kBucketGetLm(sum->ac->bucket)!=NULL){
4798      number mult_my=n_Mult(sum->c_my,sum->ac->multiplied,currRing);
4799      poly add_this;
4800      if(!nIsOne(mult_my))
4801        kBucket_Mult_n(bucket,mult_my);
4802      int len;
4803      poly clear_into;
4804      kBucketClear(sum->ac->bucket,&clear_into,&len);
4805      if(sum->ac->counter>1){
4806        add_this=pCopy(clear_into);
4807        kBucketInit(sum->ac->bucket,clear_into,len);
4808      }
4809      else
4810        add_this=clear_into;
4811      if(!nIsOne(sum->c_ac))
4812        pMult_nn(add_this, sum->c_ac);
4813     
4814      kBucket_Add_q(bucket,add_this, &len);
4815       nDelete(&mult_my);
4816     
4817    }
4818    nDelete(&sum->c_ac);
4819    nDelete(&sum->c_my);
4820   
4821    sum->ac->decrease_counter();
4822    delete sum;
4823    p=kBucketGetLm(bucket);
4824    sum=NULL;
4825  }
4826  assume(p==kBucketGetLm(bucket));
4827  assume(sum==NULL);
4828}
4829void red_object::validate(){
4830  BOOLEAN flattened=FALSE;
4831  if(sum!=NULL)
4832  {
4833    poly lm=kBucketGetLm(bucket);
4834    poly lm_ac=kBucketGetLm(sum->ac->bucket);
4835    if ((lm_ac==NULL)||((lm!=NULL) && (pLmCmp(lm,lm_ac)!=-1))){
4836      flatten();
4837      assume(sum==NULL);
4838      flattened=TRUE;
4839      p=kBucketGetLm(bucket);
4840      if (p!=NULL)
4841        sev=pGetShortExpVector(p);
4842    } 
4843    else
4844    {
4845 
4846      p=lm_ac;
4847      assume(sum->ac->sev==pGetShortExpVector(p));
4848      sev=sum->ac->sev;
4849    }
4850   
4851  }
4852  else{
4853    p=kBucketGetLm(bucket);
4854    if(p)
4855    sev=pGetShortExpVector(p);
4856  }
4857  assume((sum==NULL)||(kBucketGetLm(sum->ac->bucket)!=NULL));
4858}
4859int red_object::clear_to_poly(){
4860  flatten();
4861  int l;
4862  kBucketClear(bucket,&p,&l);
4863  return l;
4864}
4865
4866 
4867
4868void red_object::adjust_coefs(number c_r, number c_ac_r){
4869  assume(this->sum!=NULL);
4870  number n1=nMult(sum->c_my, c_ac_r);
4871  number n2=nMult(sum->c_ac,c_r);
4872  nDelete(&sum->c_my);
4873  nDelete(&sum->c_ac);
4874 
4875  int ct = ksCheckCoeff(&n1, &n2);
4876  sum->c_my=n1;
4877  sum->c_ac=nNeg(n2);
4878  //  nDelete(&n2);
4879 
4880
4881}
4882int red_object::guess_quality(calc_dat* c){
4883    //works at the moment only for lenvar 1, because in different
4884    //case, you have to look on coefs
4885    int s=0;
4886    if (c->is_char0)
4887      s=kSBucketLength(bucket);
4888    else 
4889      s=bucket_guess(bucket);
4890    if (sum!=NULL){
4891      if (c->is_char0)
4892      s+=kSBucketLength(sum->ac->bucket);
4893    else 
4894      s+=bucket_guess(sum->ac->bucket);
4895    }
4896    return s;
4897}
4898void reduction_step::reduce(red_object* r, int l, int u){}
4899void simple_reducer::target_is_no_sum_reduce(red_object & ro){
4900  kBucketPolyRed(ro.bucket,p,
4901                 p_len,
4902                 c->strat->kNoether);
4903}
4904
4905void simple_reducer::target_is_a_sum_reduce(red_object & ro){
4906  pTest(p);
4907  kbTest(ro.bucket);
4908  kbTest(ro.sum->ac->bucket);
4909  assume(ro.sum!=NULL);
4910  assume(ro.sum->ac!=NULL);
4911  if(ro.sum->ac->last_reduction_id!=reduction_id){
4912    number n1=kBucketPolyRed(ro.sum->ac->bucket,p, p_len, c->strat->kNoether);
4913    number n2=nMult(n1,ro.sum->ac->multiplied);
4914    nDelete(&ro.sum->ac->multiplied);
4915    nDelete(&n1);
4916    ro.sum->ac->multiplied=n2;
4917    poly lm=kBucketGetLm(ro.sum->ac->bucket);
4918    if (lm)
4919      ro.sum->ac->sev=pGetShortExpVector(lm);
4920    ro.sum->ac->last_reduction_id=reduction_id;
4921  }
4922  ro.sev=ro.sum->ac->sev;
4923  ro.p=kBucketGetLm(ro.sum->ac->bucket);
4924}
4925void simple_reducer::reduce(red_object* r, int l, int u){
4926  this->pre_reduce(r,l,u);
4927  int i;
4928//debug start
4929  int im;
4930//  for(im=l;im<=u;im++)
4931  //  assume(is_valid_ro(r[im]));
4932 
4933
4934//debug end
4935
4936  for(i=l;i<=u;i++){
4937 
4938
4939    if(r[i].sum==NULL)
4940      this->target_is_no_sum_reduce(r[i]);
4941
4942    else 
4943    {
4944      this->target_is_a_sum_reduce(r[i]);
4945      //reduce and adjust multiplied
4946      r[i].sum->ac->last_reduction_id=reduction_id;
4947     
4948    }
4949    //most elegant would be multimethods at this point and subclassing
4950    //red_object for sum
4951 
4952  }
4953  for(i=l;i<=u;i++){
4954    r[i].validate();
4955    #ifdef TGB_DEBUG
4956    if (r[i].sum) r[i].sev=r[i].sum->ac->sev;
4957
4958    #endif
4959      }
4960}
4961reduction_step::~reduction_step(){}
4962simple_reducer::~simple_reducer(){
4963  if(fill_back!=NULL)
4964  {
4965    kBucketInit(fill_back,p,p_len);
4966  }
4967  fill_back=NULL;
4968   
4969}
4970 join_simple_reducer::~join_simple_reducer(){
4971   if(fill_back!=NULL)
4972   {
4973     kBucketInit(fill_back,p,p_len);
4974   }
4975   fill_back=NULL;
4976   
4977}
4978void multi_reduce_step(find_erg & erg, red_object* r, calc_dat* c){
4979  static int id=0;
4980  id++;
4981
4982  int rn=erg.reduce_by;
4983  poly red;
4984  int red_len;
4985  simple_reducer* pointer;
4986  BOOLEAN woc=FALSE;
4987  if(erg.fromS){
4988    red=c->strat->S[rn];
4989    red_len=c->strat->lenS[rn];
4990   
4991  }
4992  else
4993  {
4994    r[rn].flatten();
4995    kBucketClear(r[rn].bucket,&red,&red_len);
4996    if (!rField_is_Zp(c->r))
4997    {
4998      pContent(red);
4999      pCleardenom(red);//should be unnecessary
5000     
5001    }
5002    pNormalize(red);
5003  }
5004  if (erg.to_reduce_u-erg.to_reduce_l>5){
5005    woc=TRUE;
5006    // poly m=pOne();
5007    poly m=c->tmp_lm;
5008    pSetCoeff(m,nInit(1));
5009    for(int i=1;i<=pVariables;i++)
5010      pSetExp(m,i,(pGetExp(r[erg.to_reduce_l].p, i)-pGetExp(red,i)));
5011    pSetm(m);
5012    poly red_cp=ppMult_mm(red,m);
5013   
5014    if(!erg.fromS){
5015      kBucketInit(r[rn].bucket,red,red_len);
5016    }
5017    //now reduce the copy
5018    //static poly redNF2 (poly h,calc_dat* c , int &len, number&  m,int n)
5019    redTailShort(red_cp,c->strat);
5020    //number mul;
5021    // red_len--;
5022//     red_cp->next=redNF2(red_cp->next,c,red_len,mul,c->average_length);
5023//     pSetCoeff(red_cp,nMult(red_cp->coef,mul));
5024//     nDelete(&mul);
5025//     red_len++;
5026    red=red_cp;
5027    red_len=pLength(red);
5028    // pDelete(&m);
5029   
5030  }
5031  int i;
5032
5033
5034  int red_c=0;
5035  if(red_len>2*c->average_length){
5036    for(i=erg.to_reduce_l;i<=erg.to_reduce_u;i++){
5037      if((r[i].sum==NULL) ||(r[i].sum->ac->counter<=AC_FLATTEN)) red_c++;
5038    }
5039  }
5040  if (red_c>=AC_NEW_MIN)
5041    pointer=new join_simple_reducer(red,red_len,r[erg.to_reduce_l].p);
5042  else
5043    pointer=new simple_reducer(red,red_len,c);
5044
5045  if ((!woc) && (!erg.fromS))
5046    pointer->fill_back=r[rn].bucket;
5047  else
5048    pointer->fill_back=NULL;
5049  pointer->reduction_id=id;
5050  pointer->c=c;
5051
5052  pointer->reduce(r,erg.to_reduce_l, erg.to_reduce_u);
5053  if(woc) pDelete(&pointer->p);
5054  delete pointer;
5055 
5056};
5057
5058void join_simple_reducer::target_is_no_sum_reduce(red_object & ro){
5059 
5060  ro.sum=new formal_sum_descriptor();
5061  ro.sum->ac=ac;
5062  ac->counter++;
5063  kBucket_pt bucket=ro.bucket;
5064  poly a1 = pNext(p), lm = kBucketExtractLm(bucket);
5065  BOOLEAN reset_vec=FALSE;
5066  number rn;
5067  assume(a1!=NULL);
5068  number an = pGetCoeff(p), bn = pGetCoeff(lm);
5069  lm->next=NULL;
5070  int ct = ksCheckCoeff(&an, &bn);
5071  ro.sum->c_ac=nNeg(bn);
5072  ro.sum->c_my=an;
5073  assume(nIsZero(nAdd(nMult(ro.sum->c_my,lm->coef),nMult(p->coef,ro.sum->c_ac) )));
5074  if (p_GetComp(p, bucket->bucket_ring) != p_GetComp(lm, bucket->bucket_ring))
5075  {
5076    p_SetCompP(a1, p_GetComp(lm, bucket->bucket_ring), bucket->bucket_ring);
5077    reset_vec = TRUE;
5078    p_SetComp(lm, p_GetComp(p, bucket->bucket_ring), bucket->bucket_ring);
5079    p_Setm(lm, bucket->bucket_ring);
5080  }
5081
5082
5083 
5084
5085  p_DeleteLm(&lm, bucket->bucket_ring);
5086  if (reset_vec) p_SetCompP(a1, 0, bucket->bucket_ring);
5087  kbTest(bucket);
5088
5089}
5090
5091  reduction_accumulator::reduction_accumulator(poly p, int p_len, poly high_to){
5092    //sev needs to be removed from interfaces,makes no sense
5093   
5094
5095    poly my=pOne();
5096    counter=0;
5097   
5098    for(int i=1;i<=pVariables;i++)
5099      pSetExp(my,i,(pGetExp(high_to, i)-pGetExp(p,i)));
5100    pSetm(my);
5101
5102    last_reduction_id=-1;
5103    multiplied=nInit(1);
5104    bucket=kBucketCreate(currRing);
5105    poly a=pMult_mm(pCopy(p->next),my);
5106
5107    this->sev=pGetShortExpVector(a);
5108    kBucketInit(bucket, a,p_len-1);
5109    pDelete(&my);
5110  }
5111void simple_reducer:: pre_reduce(red_object* r, int l, int u){}
5112void join_simple_reducer:: pre_reduce(red_object* r, int l, int u){
5113  for(int i=l;i<=u;i++)
5114    {
5115      if (r[i].sum){
5116        if(r[i].sum->ac->counter<=AC_FLATTEN) r[i].flatten();
5117       
5118      }
5119    }
5120}
Note: See TracBrowser for help on using the repository browser.