source: git/kernel/tgb.cc @ 6a9f2e

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