source: git/kernel/tgb.cc @ 08a955

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