source: git/kernel/tgb.cc @ f478f5b

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