source: git/libpolys/polys/monomials/p_polys.cc @ 0b0bc3

spielwiese
Last change on this file since 0b0bc3 was 0b0bc3, checked in by Hans Schoenemann <hannes@…>, 11 years ago
chg: n_Farey, p_Farey, p_ChineseRemainder from master
  • Property mode set to 100644
File size: 89.6 KB
Line 
1/****************************************
2*  Computer Algebra System SINGULAR     *
3****************************************/
4/***************************************************************
5 *  File:    p_polys.cc
6 *  Purpose: implementation of ring independent poly procedures?
7 *  Author:  obachman (Olaf Bachmann)
8 *  Created: 8/00
9 *******************************************************************/
10
11
12#include "config.h"
13
14#include <ctype.h>
15
16#include <omalloc/omalloc.h>
17
18#include <misc/auxiliary.h>
19
20#include <misc/options.h>
21#include <misc/intvec.h>
22
23#include <coeffs/longrat.h> // ???
24#include <coeffs/ffields.h>
25
26#include <polys/PolyEnumerator.h>
27
28#define TRANSEXT_PRIVATES
29
30#include <polys/ext_fields/transext.h>
31#include <polys/ext_fields/algext.h>
32
33#include <polys/weight.h>
34#include <polys/simpleideals.h>
35
36#include "ring.h"
37#include "p_polys.h"
38
39#include <polys/templates/p_MemCmp.h>
40#include <polys/templates/p_MemAdd.h>
41#include <polys/templates/p_MemCopy.h>
42
43
44// #include <???/ideals.h>
45// #include <???/int64vec.h>
46
47#ifndef NDEBUG
48// #include <???/febase.h>
49#endif
50
51#ifdef HAVE_PLURAL
52#include "nc/nc.h"
53#include "nc/sca.h"
54#endif
55
56#include "coeffrings.h"
57#ifdef HAVE_FACTORY
58#include "clapsing.h"
59#endif
60
61/*
62 * lift ideal with coeffs over Z (mod N) to Q via Farey
63 */
64poly p_Farey(poly p, number N, const ring r)
65{
66  poly h=p_Copy(p,r);
67  poly hh=h;
68  while(h!=NULL)
69  {
70    number c=pGetCoeff(h);
71    pSetCoeff0(h,n_Farey(c,N,r->cf));
72    n_Delete(&c,r->cf);
73    pIter(h);
74  }
75  while((hh!=NULL)&&(n_IsZero(pGetCoeff(hh),r->cf)))
76  {
77    p_LmDelete(&hh,r);
78  }
79  h=hh;
80  while((h!=NULL) && (pNext(h)!=NULL))
81  {
82    if(n_IsZero(pGetCoeff(pNext(h)),r->cf))
83    {
84      p_LmDelete(&pNext(h),r);
85    }
86    else pIter(h);
87  }
88  return hh;
89}
90/*2
91* xx,q: arrays of length 0..rl-1
92* xx[i]: SB mod q[i]
93* assume: char=0
94* assume: q[i]!=0
95* destroys xx
96*/
97poly p_ChineseRemainder(poly *xx, number *x,number *q, int rl, const ring R)
98{
99  poly r,h,hh;
100  int j;
101  poly  res_p=NULL;
102  loop
103  {
104    /* search the lead term */
105    r=NULL;
106    for(j=rl-1;j>=0;j--)
107    {
108      h=xx[j];
109      if ((h!=NULL)
110      &&((r==NULL)||(p_LmCmp(r,h,R)==-1)))
111        r=h;
112    }
113    /* nothing found -> return */
114    if (r==NULL) break;
115    /* create the monomial in h */
116    h=p_Head(r,R);
117    /* collect the coeffs in x[..]*/
118    for(j=rl-1;j>=0;j--)
119    {
120      hh=xx[j];
121      if ((hh!=NULL) && (p_LmCmp(r,hh,R)==0))
122      {
123        x[j]=pGetCoeff(hh);
124        hh=p_LmFreeAndNext(hh,R);
125        xx[j]=hh;
126      }
127      else
128        x[j]=n_Init(0, R);
129    }
130    number n=n_ChineseRemainder(x,q,rl,R->cf);
131    for(j=rl-1;j>=0;j--)
132    {
133      x[j]=NULL; // nlInit(0...) takes no memory
134    }
135    if (n_IsZero(n,R)) p_Delete(&h,R);
136    else
137    {
138      p_SetCoeff(h,n,R);
139      //Print("new mon:");pWrite(h);
140      pNext(h)=res_p;
141      res_p=h; // building res_p in reverse order!
142    }
143  }
144  return pReverse(res_p);
145}
146/***************************************************************
147 *
148 * Completing what needs to be set for the monomial
149 *
150 ***************************************************************/
151// this is special for the syz stuff
152static int* _components = NULL;
153static long* _componentsShifted = NULL;
154static int _componentsExternal = 0;
155
156BOOLEAN pSetm_error=0;
157
158#ifndef NDEBUG
159# define MYTEST 0
160#else /* ifndef NDEBUG */
161# define MYTEST 0
162#endif /* ifndef NDEBUG */
163
164void p_Setm_General(poly p, const ring r)
165{
166  p_LmCheckPolyRing(p, r);
167  int pos=0;
168  if (r->typ!=NULL)
169  {
170    loop
171    {
172      long ord=0;
173      sro_ord* o=&(r->typ[pos]);
174      switch(o->ord_typ)
175      {
176        case ro_dp:
177        {
178          int a,e;
179          a=o->data.dp.start;
180          e=o->data.dp.end;
181          for(int i=a;i<=e;i++) ord+=p_GetExp(p,i,r);
182          p->exp[o->data.dp.place]=ord;
183          break;
184        }
185        case ro_wp_neg:
186          ord=POLY_NEGWEIGHT_OFFSET;
187          // no break;
188        case ro_wp:
189        {
190          int a,e;
191          a=o->data.wp.start;
192          e=o->data.wp.end;
193          int *w=o->data.wp.weights;
194#if 1
195          for(int i=a;i<=e;i++) ord+=p_GetExp(p,i,r)*w[i-a];
196#else
197          long ai;
198          int ei,wi;
199          for(int i=a;i<=e;i++)
200          {
201             ei=p_GetExp(p,i,r);
202             wi=w[i-a];
203             ai=ei*wi;
204             if (ai/ei!=wi) pSetm_error=TRUE;
205             ord+=ai;
206             if (ord<ai) pSetm_error=TRUE;
207          }
208#endif
209          p->exp[o->data.wp.place]=ord;
210          break;
211        }
212        case ro_am:
213        {
214          ord = POLY_NEGWEIGHT_OFFSET;
215          const short a=o->data.am.start;
216          const short e=o->data.am.end;
217          const int * w=o->data.am.weights;
218#if 1
219          for(short i=a; i<=e; i++, w++)
220            ord += ((*w) * p_GetExp(p,i,r));
221#else
222          long ai;
223          int ei,wi;
224          for(short i=a;i<=e;i++)
225          {
226             ei=p_GetExp(p,i,r);
227             wi=w[i-a];
228             ai=ei*wi;
229             if (ai/ei!=wi) pSetm_error=TRUE;
230             ord += ai;
231             if (ord<ai) pSetm_error=TRUE;
232          }
233#endif
234          const int c = p_GetComp(p,r);
235
236          const short len_gen= o->data.am.len_gen;
237         
238          if ((c > 0) && (c <= len_gen))
239          {
240            assume( w == o->data.am.weights_m );
241            assume( w[0] == len_gen );
242            ord += w[c];
243          }
244         
245          p->exp[o->data.am.place] = ord;
246          break;
247        }
248      case ro_wp64:
249        {
250          int64 ord=0;
251          int a,e;
252          a=o->data.wp64.start;
253          e=o->data.wp64.end;
254          int64 *w=o->data.wp64.weights64;
255          int64 ei,wi,ai;
256          for(int i=a;i<=e;i++)
257          {
258            //Print("exp %d w %d \n",p_GetExp(p,i,r),(int)w[i-a]);
259            //ord+=((int64)p_GetExp(p,i,r))*w[i-a];
260            ei=(int64)p_GetExp(p,i,r);
261            wi=w[i-a];
262            ai=ei*wi;
263            if(ei!=0 && ai/ei!=wi)
264            {
265              pSetm_error=TRUE;
266              #if SIZEOF_LONG == 4
267              Print("ai %lld, wi %lld\n",ai,wi);
268              #else
269              Print("ai %ld, wi %ld\n",ai,wi);
270              #endif
271            }
272            ord+=ai;
273            if (ord<ai)
274            {
275              pSetm_error=TRUE;
276              #if SIZEOF_LONG == 4
277              Print("ai %lld, ord %lld\n",ai,ord);
278              #else
279              Print("ai %ld, ord %ld\n",ai,ord);
280              #endif
281            }
282          }
283          int64 mask=(int64)0x7fffffff;
284          long a_0=(long)(ord&mask); //2^31
285          long a_1=(long)(ord >>31 ); /*(ord/(mask+1));*/
286
287          //Print("mask: %x,  ord: %d,  a_0: %d,  a_1: %d\n"
288          //,(int)mask,(int)ord,(int)a_0,(int)a_1);
289                    //Print("mask: %d",mask);
290
291          p->exp[o->data.wp64.place]=a_1;
292          p->exp[o->data.wp64.place+1]=a_0;
293//            if(p_Setm_error) Print("***************************\n
294//                                    ***************************\n
295//                                    **WARNING: overflow error**\n
296//                                    ***************************\n
297//                                    ***************************\n");
298          break;
299        }
300        case ro_cp:
301        {
302          int a,e;
303          a=o->data.cp.start;
304          e=o->data.cp.end;
305          int pl=o->data.cp.place;
306          for(int i=a;i<=e;i++) { p->exp[pl]=p_GetExp(p,i,r); pl++; }
307          break;
308        }
309        case ro_syzcomp:
310        {
311          int c=p_GetComp(p,r);
312          long sc = c;
313          int* Components = (_componentsExternal ? _components :
314                             o->data.syzcomp.Components);
315          long* ShiftedComponents = (_componentsExternal ? _componentsShifted:
316                                     o->data.syzcomp.ShiftedComponents);
317          if (ShiftedComponents != NULL)
318          {
319            assume(Components != NULL);
320            assume(c == 0 || Components[c] != 0);
321            sc = ShiftedComponents[Components[c]];
322            assume(c == 0 || sc != 0);
323          }
324          p->exp[o->data.syzcomp.place]=sc;
325          break;
326        }
327        case ro_syz:
328        {
329          const unsigned long c = p_GetComp(p, r);
330          const short place = o->data.syz.place;
331          const int limit = o->data.syz.limit;
332
333          if (c > (unsigned long)limit)
334            p->exp[place] = o->data.syz.curr_index;
335          else if (c > 0)
336          {
337            assume( (1 <= c) && (c <= (unsigned long)limit) );
338            p->exp[place]= o->data.syz.syz_index[c];
339          }
340          else
341          {
342            assume(c == 0);
343            p->exp[place]= 0;
344          }
345          break;
346        }
347        // Prefix for Induced Schreyer ordering
348        case ro_isTemp: // Do nothing?? (to be removed into suffix later on...?)
349        {
350          assume(p != NULL);
351
352#ifndef NDEBUG
353#if MYTEST
354          Print("p_Setm_General: ro_isTemp ord: pos: %d, p: ", pos);  p_DebugPrint(p, r, r, 1);
355#endif
356#endif
357          int c = p_GetComp(p, r);
358
359          assume( c >= 0 );
360
361          // Let's simulate case ro_syz above....
362          // Should accumulate (by Suffix) and be a level indicator
363          const int* const pVarOffset = o->data.isTemp.pVarOffset;
364
365          assume( pVarOffset != NULL );
366
367          // TODO: Can this be done in the suffix???
368          for( int i = 1; i <= r->N; i++ ) // No v[0] here!!!
369          {
370            const int vo = pVarOffset[i];
371            if( vo != -1) // TODO: optimize: can be done once!
372            {
373              // Hans! Please don't break it again! p_SetExp(p, ..., r, vo) is correct:
374              p_SetExp(p, p_GetExp(p, i, r), r, vo); // copy put them verbatim
375              // Hans! Please don't break it again! p_GetExp(p, r, vo) is correct:
376              assume( p_GetExp(p, r, vo) == p_GetExp(p, i, r) ); // copy put them verbatim
377            }
378          }
379#ifndef NDEBUG
380          for( int i = 1; i <= r->N; i++ ) // No v[0] here!!!
381          {
382            const int vo = pVarOffset[i];
383            if( vo != -1) // TODO: optimize: can be done once!
384            {
385              // Hans! Please don't break it again! p_GetExp(p, r, vo) is correct:
386              assume( p_GetExp(p, r, vo) == p_GetExp(p, i, r) ); // copy put them verbatim
387            }
388          }
389#if MYTEST
390//          if( p->exp[o->data.isTemp.start] > 0 )
391            PrintS("after Values: "); p_DebugPrint(p, r, r, 1);
392#endif
393#endif
394          break;
395        }
396
397        // Suffix for Induced Schreyer ordering
398        case ro_is:
399        {
400#ifndef NDEBUG
401#if MYTEST
402          Print("p_Setm_General: ro_is ord: pos: %d, p: ", pos);  p_DebugPrint(p, r, r, 1);
403#endif
404#endif
405
406          assume(p != NULL);
407
408          int c = p_GetComp(p, r);
409
410          assume( c >= 0 );
411          const ideal F = o->data.is.F;
412          const int limit = o->data.is.limit;
413          assume( limit >= 0 );
414          const int start = o->data.is.start;
415
416          if( F != NULL && c > limit )
417          {
418#ifndef NDEBUG
419#if MYTEST
420            Print("p_Setm_General: ro_is : in rSetm: pos: %d, c: %d >  limit: %d\n", c, pos, limit); // p_DebugPrint(p, r, r, 1);
421            PrintS("preComputed Values: ");
422            p_DebugPrint(p, r, r, 1);
423#endif
424#endif
425//          if( c > limit ) // BUG???
426            p->exp[start] = 1;
427//          else
428//            p->exp[start] = 0;
429
430
431            c -= limit;
432            assume( c > 0 );
433            c--;
434
435            if( c >= IDELEMS(F) )
436              break;
437
438            assume( c < IDELEMS(F) ); // What about others???
439           
440            const poly pp = F->m[c]; // get reference monomial!!!
441
442            if(pp == NULL)
443              break;
444           
445            assume(pp != NULL);
446
447#ifndef NDEBUG
448#if MYTEST
449            Print("Respective F[c - %d: %d] pp: ", limit, c);
450            p_DebugPrint(pp, r, r, 1);
451#endif
452#endif
453
454            const int end = o->data.is.end;
455            assume(start <= end);
456
457
458//          const int st = o->data.isTemp.start;
459
460#ifndef NDEBUG
461            Print("p_Setm_General: is(-Temp-) :: c: %d, limit: %d, [st:%d] ===>>> %ld\n", c, limit, start, p->exp[start]);
462#endif
463
464            // p_ExpVectorAdd(p, pp, r);
465
466            for( int i = start; i <= end; i++) // v[0] may be here...
467              p->exp[i] += pp->exp[i]; // !!!!!!!! ADD corresponding LT(F)
468
469            // p_MemAddAdjust(p, ri);
470            if (r->NegWeightL_Offset != NULL)
471            {
472              for (int i=r->NegWeightL_Size-1; i>=0; i--)
473              {
474                const int _i = r->NegWeightL_Offset[i];
475                if( start <= _i && _i <= end )
476                  p->exp[_i] -= POLY_NEGWEIGHT_OFFSET;
477              }
478            }
479
480
481#ifndef NDEBUG
482            const int* const pVarOffset = o->data.is.pVarOffset;
483
484            assume( pVarOffset != NULL );
485
486            for( int i = 1; i <= r->N; i++ ) // No v[0] here!!!
487            {
488              const int vo = pVarOffset[i];
489              if( vo != -1) // TODO: optimize: can be done once!
490                // Hans! Please don't break it again! p_GetExp(p/pp, r, vo) is correct:
491                assume( p_GetExp(p, r, vo) == (p_GetExp(p, i, r) + p_GetExp(pp, r, vo)) );
492            }
493            // TODO: how to check this for computed values???
494#if MYTEST
495            PrintS("Computed Values: "); p_DebugPrint(p, r, r, 1);
496#endif
497#endif
498          } else
499          {
500            p->exp[start] = 0; //!!!!????? where?????
501
502            const int* const pVarOffset = o->data.is.pVarOffset;
503
504            // What about v[0] - component: it will be added later by
505            // suffix!!!
506            // TODO: Test it!
507            const int vo = pVarOffset[0];
508            if( vo != -1 )
509              p->exp[vo] = c; // initial component v[0]!
510
511#ifndef NDEBUG
512#if MYTEST
513            Print("ELSE p_Setm_General: ro_is :: c: %d <= limit: %d, vo: %d, exp: %d\n", c, limit, vo, p->exp[vo]);
514            p_DebugPrint(p, r, r, 1);
515#endif
516#endif
517          }
518
519          break;
520        }
521        default:
522          dReportError("wrong ord in rSetm:%d\n",o->ord_typ);
523          return;
524      }
525      pos++;
526      if (pos == r->OrdSize) return;
527    }
528  }
529}
530
531void p_Setm_Syz(poly p, ring r, int* Components, long* ShiftedComponents)
532{
533  _components = Components;
534  _componentsShifted = ShiftedComponents;
535  _componentsExternal = 1;
536  p_Setm_General(p, r);
537  _componentsExternal = 0;
538}
539
540// dummy for lp, ls, etc
541void p_Setm_Dummy(poly p, const ring r)
542{
543  p_LmCheckPolyRing(p, r);
544}
545
546// for dp, Dp, ds, etc
547void p_Setm_TotalDegree(poly p, const ring r)
548{
549  p_LmCheckPolyRing(p, r);
550  p->exp[r->pOrdIndex] = p_Totaldegree(p, r);
551}
552
553// for wp, Wp, ws, etc
554void p_Setm_WFirstTotalDegree(poly p, const ring r)
555{
556  p_LmCheckPolyRing(p, r);
557  p->exp[r->pOrdIndex] = p_WFirstTotalDegree(p, r);
558}
559
560p_SetmProc p_GetSetmProc(ring r)
561{
562  // covers lp, rp, ls,
563  if (r->typ == NULL) return p_Setm_Dummy;
564
565  if (r->OrdSize == 1)
566  {
567    if (r->typ[0].ord_typ == ro_dp &&
568        r->typ[0].data.dp.start == 1 &&
569        r->typ[0].data.dp.end == r->N &&
570        r->typ[0].data.dp.place == r->pOrdIndex)
571      return p_Setm_TotalDegree;
572    if (r->typ[0].ord_typ == ro_wp &&
573        r->typ[0].data.wp.start == 1 &&
574        r->typ[0].data.wp.end == r->N &&
575        r->typ[0].data.wp.place == r->pOrdIndex &&
576        r->typ[0].data.wp.weights == r->firstwv)
577      return p_Setm_WFirstTotalDegree;
578  }
579  return p_Setm_General;
580}
581
582
583/* -------------------------------------------------------------------*/
584/* several possibilities for pFDeg: the degree of the head term       */
585
586/* comptible with ordering */
587long p_Deg(poly a, const ring r)
588{
589  p_LmCheckPolyRing(a, r);
590//  assume(p_GetOrder(a, r) == p_WTotaldegree(a, r)); // WRONG assume!
591  return p_GetOrder(a, r);
592}
593
594// p_WTotalDegree for weighted orderings
595// whose first block covers all variables
596long p_WFirstTotalDegree(poly p, const ring r)
597{
598  int i;
599  long sum = 0;
600
601  for (i=1; i<= r->firstBlockEnds; i++)
602  {
603    sum += p_GetExp(p, i, r)*r->firstwv[i-1];
604  }
605  return sum;
606}
607
608/*2
609* compute the degree of the leading monomial of p
610* with respect to weigths from the ordering
611* the ordering is not compatible with degree so do not use p->Order
612*/
613long p_WTotaldegree(poly p, const ring r)
614{
615  p_LmCheckPolyRing(p, r);
616  int i, k;
617  long j =0;
618
619  // iterate through each block:
620  for (i=0;r->order[i]!=0;i++)
621  {
622    int b0=r->block0[i];
623    int b1=r->block1[i];
624    switch(r->order[i])
625    {
626      case ringorder_M:
627        for (k=b0 /*r->block0[i]*/;k<=b1 /*r->block1[i]*/;k++)
628        { // in jedem block:
629          j+= p_GetExp(p,k,r)*r->wvhdl[i][k - b0 /*r->block0[i]*/]*r->OrdSgn;
630        }
631        break;
632      case ringorder_wp:
633      case ringorder_ws:
634      case ringorder_Wp:
635      case ringorder_Ws:
636        for (k=b0 /*r->block0[i]*/;k<=b1 /*r->block1[i]*/;k++)
637        { // in jedem block:
638          j+= p_GetExp(p,k,r)*r->wvhdl[i][k - b0 /*r->block0[i]*/];
639        }
640        break;
641      case ringorder_lp:
642      case ringorder_ls:
643      case ringorder_rs:
644      case ringorder_dp:
645      case ringorder_ds:
646      case ringorder_Dp:
647      case ringorder_Ds:
648      case ringorder_rp:
649        for (k=b0 /*r->block0[i]*/;k<=b1 /*r->block1[i]*/;k++)
650        {
651          j+= p_GetExp(p,k,r);
652        }
653        break;
654      case ringorder_a64:
655        {
656          int64* w=(int64*)r->wvhdl[i];
657          for (k=0;k<=(b1 /*r->block1[i]*/ - b0 /*r->block0[i]*/);k++)
658          {
659            //there should be added a line which checks if w[k]>2^31
660            j+= p_GetExp(p,k+1, r)*(long)w[k];
661          }
662          //break;
663          return j;
664        }
665      case ringorder_c:
666      case ringorder_C:
667      case ringorder_S:
668      case ringorder_s:
669      case ringorder_aa:
670      case ringorder_IS:
671        break;
672      case ringorder_a:
673        for (k=b0 /*r->block0[i]*/;k<=b1 /*r->block1[i]*/;k++)
674        { // only one line
675          j+= p_GetExp(p,k, r)*r->wvhdl[i][ k- b0 /*r->block0[i]*/];
676        }
677        //break;
678        return j;
679
680#ifndef NDEBUG
681      default:
682        Print("missing order %d in p_WTotaldegree\n",r->order[i]);
683        break;
684#endif
685    }
686  }
687  return  j;
688}
689
690long p_DegW(poly p, const short *w, const ring R)
691{
692  long r=~0L;
693
694  while (p!=NULL)
695  {
696    long t=totaldegreeWecart_IV(p,R,w);
697    if (t>r) r=t;
698    pIter(p);
699  }
700  return r;
701}
702
703int p_Weight(int i, const ring r)
704{
705  if ((r->firstwv==NULL) || (i>r->firstBlockEnds))
706  {
707    return 1;
708  }
709  return r->firstwv[i-1];
710}
711
712long p_WDegree(poly p, const ring r)
713{
714  if (r->firstwv==NULL) return p_Totaldegree(p, r);
715  p_LmCheckPolyRing(p, r);
716  int i;
717  long j =0;
718
719  for(i=1;i<=r->firstBlockEnds;i++)
720    j+=p_GetExp(p, i, r)*r->firstwv[i-1];
721
722  for (;i<=r->N;i++)
723    j+=p_GetExp(p,i, r)*p_Weight(i, r);
724
725  return j;
726}
727
728
729/* ---------------------------------------------------------------------*/
730/* several possibilities for pLDeg: the maximal degree of a monomial in p*/
731/*  compute in l also the pLength of p                                   */
732
733/*2
734* compute the length of a polynomial (in l)
735* and the degree of the monomial with maximal degree: the last one
736*/
737long pLDeg0(poly p,int *l, const ring r)
738{
739  p_CheckPolyRing(p, r);
740  long k= p_GetComp(p, r);
741  int ll=1;
742
743  if (k > 0)
744  {
745    while ((pNext(p)!=NULL) && (p_GetComp(pNext(p), r)==k))
746    {
747      pIter(p);
748      ll++;
749    }
750  }
751  else
752  {
753     while (pNext(p)!=NULL)
754     {
755       pIter(p);
756       ll++;
757     }
758  }
759  *l=ll;
760  return r->pFDeg(p, r);
761}
762
763/*2
764* compute the length of a polynomial (in l)
765* and the degree of the monomial with maximal degree: the last one
766* but search in all components before syzcomp
767*/
768long pLDeg0c(poly p,int *l, const ring r)
769{
770  assume(p!=NULL);
771#ifdef PDEBUG
772  _p_Test(p,r,PDEBUG);
773#endif
774  p_CheckPolyRing(p, r);
775  long o;
776  int ll=1;
777
778  if (! rIsSyzIndexRing(r))
779  {
780    while (pNext(p) != NULL)
781    {
782      pIter(p);
783      ll++;
784    }
785    o = r->pFDeg(p, r);
786  }
787  else
788  {
789    int curr_limit = rGetCurrSyzLimit(r);
790    poly pp = p;
791    while ((p=pNext(p))!=NULL)
792    {
793      if (p_GetComp(p, r)<=curr_limit/*syzComp*/)
794        ll++;
795      else break;
796      pp = p;
797    }
798#ifdef PDEBUG
799    _p_Test(pp,r,PDEBUG);
800#endif
801    o = r->pFDeg(pp, r);
802  }
803  *l=ll;
804  return o;
805}
806
807/*2
808* compute the length of a polynomial (in l)
809* and the degree of the monomial with maximal degree: the first one
810* this works for the polynomial case with degree orderings
811* (both c,dp and dp,c)
812*/
813long pLDegb(poly p,int *l, const ring r)
814{
815  p_CheckPolyRing(p, r);
816  long k= p_GetComp(p, r);
817  long o = r->pFDeg(p, r);
818  int ll=1;
819
820  if (k != 0)
821  {
822    while (((p=pNext(p))!=NULL) && (p_GetComp(p, r)==k))
823    {
824      ll++;
825    }
826  }
827  else
828  {
829    while ((p=pNext(p)) !=NULL)
830    {
831      ll++;
832    }
833  }
834  *l=ll;
835  return o;
836}
837
838/*2
839* compute the length of a polynomial (in l)
840* and the degree of the monomial with maximal degree:
841* this is NOT the last one, we have to look for it
842*/
843long pLDeg1(poly p,int *l, const ring r)
844{
845  p_CheckPolyRing(p, r);
846  long k= p_GetComp(p, r);
847  int ll=1;
848  long  t,max;
849
850  max=r->pFDeg(p, r);
851  if (k > 0)
852  {
853    while (((p=pNext(p))!=NULL) && (p_GetComp(p, r)==k))
854    {
855      t=r->pFDeg(p, r);
856      if (t>max) max=t;
857      ll++;
858    }
859  }
860  else
861  {
862    while ((p=pNext(p))!=NULL)
863    {
864      t=r->pFDeg(p, r);
865      if (t>max) max=t;
866      ll++;
867    }
868  }
869  *l=ll;
870  return max;
871}
872
873/*2
874* compute the length of a polynomial (in l)
875* and the degree of the monomial with maximal degree:
876* this is NOT the last one, we have to look for it
877* in all components
878*/
879long pLDeg1c(poly p,int *l, const ring r)
880{
881  p_CheckPolyRing(p, r);
882  int ll=1;
883  long  t,max;
884
885  max=r->pFDeg(p, r);
886  if (rIsSyzIndexRing(r))
887  {
888    long limit = rGetCurrSyzLimit(r);
889    while ((p=pNext(p))!=NULL)
890    {
891      if (p_GetComp(p, r)<=limit)
892      {
893        if ((t=r->pFDeg(p, r))>max) max=t;
894        ll++;
895      }
896      else break;
897    }
898  }
899  else
900  {
901    while ((p=pNext(p))!=NULL)
902    {
903      if ((t=r->pFDeg(p, r))>max) max=t;
904      ll++;
905    }
906  }
907  *l=ll;
908  return max;
909}
910
911// like pLDeg1, only pFDeg == pDeg
912long pLDeg1_Deg(poly p,int *l, const ring r)
913{
914  assume(r->pFDeg == p_Deg);
915  p_CheckPolyRing(p, r);
916  long k= p_GetComp(p, r);
917  int ll=1;
918  long  t,max;
919
920  max=p_GetOrder(p, r);
921  if (k > 0)
922  {
923    while (((p=pNext(p))!=NULL) && (p_GetComp(p, r)==k))
924    {
925      t=p_GetOrder(p, r);
926      if (t>max) max=t;
927      ll++;
928    }
929  }
930  else
931  {
932    while ((p=pNext(p))!=NULL)
933    {
934      t=p_GetOrder(p, r);
935      if (t>max) max=t;
936      ll++;
937    }
938  }
939  *l=ll;
940  return max;
941}
942
943long pLDeg1c_Deg(poly p,int *l, const ring r)
944{
945  assume(r->pFDeg == p_Deg);
946  p_CheckPolyRing(p, r);
947  int ll=1;
948  long  t,max;
949
950  max=p_GetOrder(p, r);
951  if (rIsSyzIndexRing(r))
952  {
953    long limit = rGetCurrSyzLimit(r);
954    while ((p=pNext(p))!=NULL)
955    {
956      if (p_GetComp(p, r)<=limit)
957      {
958        if ((t=p_GetOrder(p, r))>max) max=t;
959        ll++;
960      }
961      else break;
962    }
963  }
964  else
965  {
966    while ((p=pNext(p))!=NULL)
967    {
968      if ((t=p_GetOrder(p, r))>max) max=t;
969      ll++;
970    }
971  }
972  *l=ll;
973  return max;
974}
975
976// like pLDeg1, only pFDeg == pTotoalDegree
977long pLDeg1_Totaldegree(poly p,int *l, const ring r)
978{
979  p_CheckPolyRing(p, r);
980  long k= p_GetComp(p, r);
981  int ll=1;
982  long  t,max;
983
984  max=p_Totaldegree(p, r);
985  if (k > 0)
986  {
987    while (((p=pNext(p))!=NULL) && (p_GetComp(p, r)==k))
988    {
989      t=p_Totaldegree(p, r);
990      if (t>max) max=t;
991      ll++;
992    }
993  }
994  else
995  {
996    while ((p=pNext(p))!=NULL)
997    {
998      t=p_Totaldegree(p, r);
999      if (t>max) max=t;
1000      ll++;
1001    }
1002  }
1003  *l=ll;
1004  return max;
1005}
1006
1007long pLDeg1c_Totaldegree(poly p,int *l, const ring r)
1008{
1009  p_CheckPolyRing(p, r);
1010  int ll=1;
1011  long  t,max;
1012
1013  max=p_Totaldegree(p, r);
1014  if (rIsSyzIndexRing(r))
1015  {
1016    long limit = rGetCurrSyzLimit(r);
1017    while ((p=pNext(p))!=NULL)
1018    {
1019      if (p_GetComp(p, r)<=limit)
1020      {
1021        if ((t=p_Totaldegree(p, r))>max) max=t;
1022        ll++;
1023      }
1024      else break;
1025    }
1026  }
1027  else
1028  {
1029    while ((p=pNext(p))!=NULL)
1030    {
1031      if ((t=p_Totaldegree(p, r))>max) max=t;
1032      ll++;
1033    }
1034  }
1035  *l=ll;
1036  return max;
1037}
1038
1039// like pLDeg1, only pFDeg == p_WFirstTotalDegree
1040long pLDeg1_WFirstTotalDegree(poly p,int *l, const ring r)
1041{
1042  p_CheckPolyRing(p, r);
1043  long k= p_GetComp(p, r);
1044  int ll=1;
1045  long  t,max;
1046
1047  max=p_WFirstTotalDegree(p, r);
1048  if (k > 0)
1049  {
1050    while (((p=pNext(p))!=NULL) && (p_GetComp(p, r)==k))
1051    {
1052      t=p_WFirstTotalDegree(p, r);
1053      if (t>max) max=t;
1054      ll++;
1055    }
1056  }
1057  else
1058  {
1059    while ((p=pNext(p))!=NULL)
1060    {
1061      t=p_WFirstTotalDegree(p, r);
1062      if (t>max) max=t;
1063      ll++;
1064    }
1065  }
1066  *l=ll;
1067  return max;
1068}
1069
1070long pLDeg1c_WFirstTotalDegree(poly p,int *l, const ring r)
1071{
1072  p_CheckPolyRing(p, r);
1073  int ll=1;
1074  long  t,max;
1075
1076  max=p_WFirstTotalDegree(p, r);
1077  if (rIsSyzIndexRing(r))
1078  {
1079    long limit = rGetCurrSyzLimit(r);
1080    while ((p=pNext(p))!=NULL)
1081    {
1082      if (p_GetComp(p, r)<=limit)
1083      {
1084        if ((t=p_Totaldegree(p, r))>max) max=t;
1085        ll++;
1086      }
1087      else break;
1088    }
1089  }
1090  else
1091  {
1092    while ((p=pNext(p))!=NULL)
1093    {
1094      if ((t=p_Totaldegree(p, r))>max) max=t;
1095      ll++;
1096    }
1097  }
1098  *l=ll;
1099  return max;
1100}
1101
1102/***************************************************************
1103 *
1104 * Maximal Exponent business
1105 *
1106 ***************************************************************/
1107
1108static inline unsigned long
1109p_GetMaxExpL2(unsigned long l1, unsigned long l2, const ring r,
1110              unsigned long number_of_exp)
1111{
1112  const unsigned long bitmask = r->bitmask;
1113  unsigned long ml1 = l1 & bitmask;
1114  unsigned long ml2 = l2 & bitmask;
1115  unsigned long max = (ml1 > ml2 ? ml1 : ml2);
1116  unsigned long j = number_of_exp - 1;
1117
1118  if (j > 0)
1119  {
1120    unsigned long mask = bitmask << r->BitsPerExp;
1121    while (1)
1122    {
1123      ml1 = l1 & mask;
1124      ml2 = l2 & mask;
1125      max |= ((ml1 > ml2 ? ml1 : ml2) & mask);
1126      j--;
1127      if (j == 0) break;
1128      mask = mask << r->BitsPerExp;
1129    }
1130  }
1131  return max;
1132}
1133
1134static inline unsigned long
1135p_GetMaxExpL2(unsigned long l1, unsigned long l2, const ring r)
1136{
1137  return p_GetMaxExpL2(l1, l2, r, r->ExpPerLong);
1138}
1139
1140poly p_GetMaxExpP(poly p, const ring r)
1141{
1142  p_CheckPolyRing(p, r);
1143  if (p == NULL) return p_Init(r);
1144  poly max = p_LmInit(p, r);
1145  pIter(p);
1146  if (p == NULL) return max;
1147  int i, offset;
1148  unsigned long l_p, l_max;
1149  unsigned long divmask = r->divmask;
1150
1151  do
1152  {
1153    offset = r->VarL_Offset[0];
1154    l_p = p->exp[offset];
1155    l_max = max->exp[offset];
1156    // do the divisibility trick to find out whether l has an exponent
1157    if (l_p > l_max ||
1158        (((l_max & divmask) ^ (l_p & divmask)) != ((l_max-l_p) & divmask)))
1159      max->exp[offset] = p_GetMaxExpL2(l_max, l_p, r);
1160
1161    for (i=1; i<r->VarL_Size; i++)
1162    {
1163      offset = r->VarL_Offset[i];
1164      l_p = p->exp[offset];
1165      l_max = max->exp[offset];
1166      // do the divisibility trick to find out whether l has an exponent
1167      if (l_p > l_max ||
1168          (((l_max & divmask) ^ (l_p & divmask)) != ((l_max-l_p) & divmask)))
1169        max->exp[offset] = p_GetMaxExpL2(l_max, l_p, r);
1170    }
1171    pIter(p);
1172  }
1173  while (p != NULL);
1174  return max;
1175}
1176
1177unsigned long p_GetMaxExpL(poly p, const ring r, unsigned long l_max)
1178{
1179  unsigned long l_p, divmask = r->divmask;
1180  int i;
1181
1182  while (p != NULL)
1183  {
1184    l_p = p->exp[r->VarL_Offset[0]];
1185    if (l_p > l_max ||
1186        (((l_max & divmask) ^ (l_p & divmask)) != ((l_max-l_p) & divmask)))
1187      l_max = p_GetMaxExpL2(l_max, l_p, r);
1188    for (i=1; i<r->VarL_Size; i++)
1189    {
1190      l_p = p->exp[r->VarL_Offset[i]];
1191      // do the divisibility trick to find out whether l has an exponent
1192      if (l_p > l_max ||
1193          (((l_max & divmask) ^ (l_p & divmask)) != ((l_max-l_p) & divmask)))
1194        l_max = p_GetMaxExpL2(l_max, l_p, r);
1195    }
1196    pIter(p);
1197  }
1198  return l_max;
1199}
1200
1201
1202
1203
1204/***************************************************************
1205 *
1206 * Misc things
1207 *
1208 ***************************************************************/
1209// returns TRUE, if all monoms have the same component
1210BOOLEAN p_OneComp(poly p, const ring r)
1211{
1212  if(p!=NULL)
1213  {
1214    long i = p_GetComp(p, r);
1215    while (pNext(p)!=NULL)
1216    {
1217      pIter(p);
1218      if(i != p_GetComp(p, r)) return FALSE;
1219    }
1220  }
1221  return TRUE;
1222}
1223
1224/*2
1225*test if a monomial /head term is a pure power
1226*/
1227int p_IsPurePower(const poly p, const ring r)
1228{
1229  int i,k=0;
1230
1231  for (i=r->N;i;i--)
1232  {
1233    if (p_GetExp(p,i, r)!=0)
1234    {
1235      if(k!=0) return 0;
1236      k=i;
1237    }
1238  }
1239  return k;
1240}
1241
1242/*2
1243*test if a polynomial is univariate
1244* return -1 for constant,
1245* 0 for not univariate,s
1246* i if dep. on var(i)
1247*/
1248int p_IsUnivariate(poly p, const ring r)
1249{
1250  int i,k=-1;
1251
1252  while (p!=NULL)
1253  {
1254    for (i=r->N;i;i--)
1255    {
1256      if (p_GetExp(p,i, r)!=0)
1257      {
1258        if((k!=-1)&&(k!=i)) return 0;
1259        k=i;
1260      }
1261    }
1262    pIter(p);
1263  }
1264  return k;
1265}
1266
1267// set entry e[i] to 1 if var(i) occurs in p, ignore var(j) if e[j]>0
1268int  p_GetVariables(poly p, int * e, const ring r)
1269{
1270  int i;
1271  int n=0;
1272  while(p!=NULL)
1273  {
1274    n=0;
1275    for(i=r->N; i>0; i--)
1276    {
1277      if(e[i]==0)
1278      {
1279        if (p_GetExp(p,i,r)>0)
1280        {
1281          e[i]=1;
1282          n++;
1283        }
1284      }
1285      else
1286        n++;
1287    }
1288    if (n==r->N) break;
1289    pIter(p);
1290  }
1291  return n;
1292}
1293
1294
1295/*2
1296* returns a polynomial representing the integer i
1297*/
1298poly p_ISet(long i, const ring r)
1299{
1300  poly rc = NULL;
1301  if (i!=0)
1302  {
1303    rc = p_Init(r);
1304    pSetCoeff0(rc,n_Init(i,r->cf));
1305    if (n_IsZero(pGetCoeff(rc),r->cf))
1306      p_LmDelete(&rc,r);
1307  }
1308  return rc;
1309}
1310
1311/*2
1312* an optimized version of p_ISet for the special case 1
1313*/
1314poly p_One(const ring r)
1315{
1316  poly rc = p_Init(r);
1317  pSetCoeff0(rc,n_Init(1,r->cf));
1318  return rc;
1319}
1320
1321void p_Split(poly p, poly *h)
1322{
1323  *h=pNext(p);
1324  pNext(p)=NULL;
1325}
1326
1327/*2
1328* pair has no common factor ? or is no polynomial
1329*/
1330BOOLEAN p_HasNotCF(poly p1, poly p2, const ring r)
1331{
1332
1333  if (p_GetComp(p1,r) > 0 || p_GetComp(p2,r) > 0)
1334    return FALSE;
1335  int i = rVar(r);
1336  loop
1337  {
1338    if ((p_GetExp(p1, i, r) > 0) && (p_GetExp(p2, i, r) > 0))
1339      return FALSE;
1340    i--;
1341    if (i == 0)
1342      return TRUE;
1343  }
1344}
1345
1346/*2
1347* convert monomial given as string to poly, e.g. 1x3y5z
1348*/
1349const char * p_Read(const char *st, poly &rc, const ring r)
1350{
1351  if (r==NULL) { rc=NULL;return st;}
1352  int i,j;
1353  rc = p_Init(r);
1354  const char *s = r->cf->cfRead(st,&(rc->coef),r->cf);
1355  if (s==st)
1356  /* i.e. it does not start with a coeff: test if it is a ringvar*/
1357  {
1358    j = r_IsRingVar(s,r);
1359    if (j >= 0)
1360    {
1361      p_IncrExp(rc,1+j,r);
1362      while (*s!='\0') s++;
1363      goto done;
1364    }
1365  }
1366  while (*s!='\0')
1367  {
1368    char ss[2];
1369    ss[0] = *s++;
1370    ss[1] = '\0';
1371    j = r_IsRingVar(ss,r);
1372    if (j >= 0)
1373    {
1374      const char *s_save=s;
1375      s = eati(s,&i);
1376      if (((unsigned long)i) >  r->bitmask)
1377      {
1378        // exponent to large: it is not a monomial
1379        p_LmDelete(&rc,r);
1380        return s_save;
1381      }
1382      p_AddExp(rc,1+j, (long)i, r);
1383    }
1384    else
1385    {
1386      // 1st char of is not a varname
1387      // We return the parsed polynomial nevertheless. This is needed when
1388      // we are parsing coefficients in a rational function field.
1389      s--;
1390      return s;
1391    }
1392  }
1393done:
1394  if (n_IsZero(pGetCoeff(rc),r->cf)) p_LmDelete(&rc,r);
1395  else
1396  {
1397#ifdef HAVE_PLURAL
1398    // in super-commutative ring
1399    // squares of anti-commutative variables are zeroes!
1400    if(rIsSCA(r))
1401    {
1402      const unsigned int iFirstAltVar = scaFirstAltVar(r);
1403      const unsigned int iLastAltVar  = scaLastAltVar(r);
1404
1405      assume(rc != NULL);
1406
1407      for(unsigned int k = iFirstAltVar; k <= iLastAltVar; k++)
1408        if( p_GetExp(rc, k, r) > 1 )
1409        {
1410          p_LmDelete(&rc, r);
1411          goto finish;
1412        }
1413    }
1414#endif
1415
1416    p_Setm(rc,r);
1417  }
1418finish:
1419  return s;
1420}
1421poly p_mInit(const char *st, BOOLEAN &ok, const ring r)
1422{
1423  poly p;
1424  const char *s=p_Read(st,p,r);
1425  if (*s!='\0')
1426  {
1427    if ((s!=st)&&isdigit(st[0]))
1428    {
1429      errorreported=TRUE;
1430    }
1431    ok=FALSE;
1432    p_Delete(&p,r);
1433    return NULL;
1434  }
1435  #ifdef PDEBUG
1436  _p_Test(p,r,PDEBUG);
1437  #endif
1438  ok=!errorreported;
1439  return p;
1440}
1441
1442/*2
1443* returns a polynomial representing the number n
1444* destroys n
1445*/
1446poly p_NSet(number n, const ring r)
1447{
1448  if (n_IsZero(n,r->cf))
1449  {
1450    n_Delete(&n, r->cf);
1451    return NULL;
1452  }
1453  else
1454  {
1455    poly rc = p_Init(r);
1456    pSetCoeff0(rc,n);
1457    return rc;
1458  }
1459}
1460/*2
1461* assumes that LM(a) = LM(b)*m, for some monomial m,
1462* returns the multiplicant m,
1463* leaves a and b unmodified
1464*/
1465poly p_Divide(poly a, poly b, const ring r)
1466{
1467  assume((p_GetComp(a,r)==p_GetComp(b,r)) || (p_GetComp(b,r)==0));
1468  int i;
1469  poly result = p_Init(r);
1470
1471  for(i=(int)r->N; i; i--)
1472    p_SetExp(result,i, p_GetExp(a,i,r)- p_GetExp(b,i,r),r);
1473  p_SetComp(result, p_GetComp(a,r) - p_GetComp(b,r),r);
1474  p_Setm(result,r);
1475  return result;
1476}
1477
1478poly p_Div_nn(poly p, const number n, const ring r)
1479{
1480  pAssume(!n_IsZero(n,r->cf));
1481  p_Test(p, r);
1482
1483  poly q = p;
1484  while (p != NULL)
1485  {
1486    number nc = pGetCoeff(p);
1487    pSetCoeff0(p, n_Div(nc, n, r->cf));
1488    n_Delete(&nc, r->cf);
1489    pIter(p);
1490  }
1491  p_Test(q, r);
1492  return q;
1493}
1494
1495/*2
1496* divides a by the monomial b, ignores monomials which are not divisible
1497* assumes that b is not NULL, destroyes b
1498*/
1499poly p_DivideM(poly a, poly b, const ring r)
1500{
1501  if (a==NULL) { p_Delete(&b,r); return NULL; }
1502  poly result=a;
1503  poly prev=NULL;
1504  int i;
1505#ifdef HAVE_RINGS
1506  number inv=pGetCoeff(b);
1507#else
1508  number inv=n_Invers(pGetCoeff(b),r->cf);
1509#endif
1510
1511  while (a!=NULL)
1512  {
1513    if (p_DivisibleBy(b,a,r))
1514    {
1515      for(i=(int)r->N; i; i--)
1516         p_SubExp(a,i, p_GetExp(b,i,r),r);
1517      p_SubComp(a, p_GetComp(b,r),r);
1518      p_Setm(a,r);
1519      prev=a;
1520      pIter(a);
1521    }
1522    else
1523    {
1524      if (prev==NULL)
1525      {
1526        p_LmDelete(&result,r);
1527        a=result;
1528      }
1529      else
1530      {
1531        p_LmDelete(&pNext(prev),r);
1532        a=pNext(prev);
1533      }
1534    }
1535  }
1536#ifdef HAVE_RINGS
1537  if (n_IsUnit(inv,r->cf))
1538  {
1539    inv = n_Invers(inv,r->cf);
1540    p_Mult_nn(result,inv,r);
1541    n_Delete(&inv, r->cf);
1542  }
1543  else
1544  {
1545    p_Div_nn(result,inv,r);
1546  }
1547#else
1548  p_Mult_nn(result,inv,r);
1549  n_Delete(&inv, r->cf);
1550#endif
1551  p_Delete(&b, r);
1552  return result;
1553}
1554
1555#ifdef HAVE_RINGS
1556/* TRUE iff LT(f) | LT(g) */
1557BOOLEAN p_DivisibleByRingCase(poly f, poly g, const ring r)
1558{
1559  int exponent;
1560  for(int i = (int)rVar(r); i>0; i--)
1561  {
1562    exponent = p_GetExp(g, i, r) - p_GetExp(f, i, r);
1563    if (exponent < 0) return FALSE;
1564  }
1565  return n_DivBy(pGetCoeff(g), pGetCoeff(f), r->cf);
1566}
1567#endif
1568
1569// returns the LCM of the head terms of a and b in *m
1570void p_Lcm(const poly a, const poly b, poly m, const ring r)
1571{
1572  for (int i=rVar(r); i; --i)
1573    p_SetExp(m,i, si_max( p_GetExp(a,i,r), p_GetExp(b,i,r)),r);
1574 
1575  p_SetComp(m, si_max(p_GetComp(a,r), p_GetComp(b,r)),r);
1576  /* Don't do a pSetm here, otherwise hres/lres chockes */
1577}
1578
1579/* assumes that p and divisor are univariate polynomials in r,
1580   mentioning the same variable;
1581   assumes divisor != NULL;
1582   p may be NULL;
1583   assumes a global monomial ordering in r;
1584   performs polynomial division of p by divisor:
1585     - afterwards p contains the remainder of the division, i.e.,
1586       p_before = result * divisor + p_afterwards;
1587     - if needResult == TRUE, then the method computes and returns 'result',
1588       otherwise NULL is returned (This parametrization can be used when
1589       one is only interested in the remainder of the division. In this
1590       case, the method will be slightly faster.)
1591   leaves divisor unmodified */
1592poly      p_PolyDiv(poly &p, const poly divisor, const BOOLEAN needResult, const ring r)
1593{
1594  assume(divisor != NULL);
1595  if (p == NULL) return NULL;
1596
1597  poly result = NULL;
1598  number divisorLC = p_GetCoeff(divisor, r);
1599  int divisorLE = p_GetExp(divisor, 1, r);
1600  while ((p != NULL) && (p_Deg(p, r) >= p_Deg(divisor, r)))
1601  {
1602    /* determine t = LT(p) / LT(divisor) */
1603    poly t = p_ISet(1, r);
1604    number c = n_Div(p_GetCoeff(p, r), divisorLC, r->cf);
1605    n_Normalize(c,r->cf);
1606    p_SetCoeff(t, c, r);
1607    int e = p_GetExp(p, 1, r) - divisorLE;
1608    p_SetExp(t, 1, e, r);
1609    p_Setm(t, r);
1610    if (needResult) result = p_Add_q(result, p_Copy(t, r), r);
1611    p = p_Add_q(p, p_Neg(p_Mult_q(t, p_Copy(divisor, r), r), r), r);
1612  }
1613  return result;
1614}
1615
1616/*2
1617* returns the partial differentiate of a by the k-th variable
1618* does not destroy the input
1619*/
1620poly p_Diff(poly a, int k, const ring r)
1621{
1622  poly res, f, last;
1623  number t;
1624
1625  last = res = NULL;
1626  while (a!=NULL)
1627  {
1628    if (p_GetExp(a,k,r)!=0)
1629    {
1630      f = p_LmInit(a,r);
1631      t = n_Init(p_GetExp(a,k,r),r->cf);
1632      pSetCoeff0(f,n_Mult(t,pGetCoeff(a),r->cf));
1633      n_Delete(&t,r->cf);
1634      if (n_IsZero(pGetCoeff(f),r->cf))
1635        p_LmDelete(&f,r);
1636      else
1637      {
1638        p_DecrExp(f,k,r);
1639        p_Setm(f,r);
1640        if (res==NULL)
1641        {
1642          res=last=f;
1643        }
1644        else
1645        {
1646          pNext(last)=f;
1647          last=f;
1648        }
1649      }
1650    }
1651    pIter(a);
1652  }
1653  return res;
1654}
1655
1656static poly p_DiffOpM(poly a, poly b,BOOLEAN multiply, const ring r)
1657{
1658  int i,j,s;
1659  number n,h,hh;
1660  poly p=p_One(r);
1661  n=n_Mult(pGetCoeff(a),pGetCoeff(b),r->cf);
1662  for(i=rVar(r);i>0;i--)
1663  {
1664    s=p_GetExp(b,i,r);
1665    if (s<p_GetExp(a,i,r))
1666    {
1667      n_Delete(&n,r->cf);
1668      p_LmDelete(&p,r);
1669      return NULL;
1670    }
1671    if (multiply)
1672    {
1673      for(j=p_GetExp(a,i,r); j>0;j--)
1674      {
1675        h = n_Init(s,r->cf);
1676        hh=n_Mult(n,h,r->cf);
1677        n_Delete(&h,r->cf);
1678        n_Delete(&n,r->cf);
1679        n=hh;
1680        s--;
1681      }
1682      p_SetExp(p,i,s,r);
1683    }
1684    else
1685    {
1686      p_SetExp(p,i,s-p_GetExp(a,i,r),r);
1687    }
1688  }
1689  p_Setm(p,r);
1690  /*if (multiply)*/ p_SetCoeff(p,n,r);
1691  if (n_IsZero(n,r->cf))  p=p_LmDeleteAndNext(p,r); // return NULL as p is a monomial
1692  return p;
1693}
1694
1695poly p_DiffOp(poly a, poly b,BOOLEAN multiply, const ring r)
1696{
1697  poly result=NULL;
1698  poly h;
1699  for(;a!=NULL;pIter(a))
1700  {
1701    for(h=b;h!=NULL;pIter(h))
1702    {
1703      result=p_Add_q(result,p_DiffOpM(a,h,multiply,r),r);
1704    }
1705  }
1706  return result;
1707}
1708/*2
1709* subtract p2 from p1, p1 and p2 are destroyed
1710* do not put attention on speed: the procedure is only used in the interpreter
1711*/
1712poly p_Sub(poly p1, poly p2, const ring r)
1713{
1714  return p_Add_q(p1, p_Neg(p2,r),r);
1715}
1716
1717/*3
1718* compute for a monomial m
1719* the power m^exp, exp > 1
1720* destroys p
1721*/
1722static poly p_MonPower(poly p, int exp, const ring r)
1723{
1724  int i;
1725
1726  if(!n_IsOne(pGetCoeff(p),r->cf))
1727  {
1728    number x, y;
1729    y = pGetCoeff(p);
1730    n_Power(y,exp,&x,r->cf);
1731    n_Delete(&y,r->cf);
1732    pSetCoeff0(p,x);
1733  }
1734  for (i=rVar(r); i!=0; i--)
1735  {
1736    p_MultExp(p,i, exp,r);
1737  }
1738  p_Setm(p,r);
1739  return p;
1740}
1741
1742/*3
1743* compute for monomials p*q
1744* destroys p, keeps q
1745*/
1746static void p_MonMult(poly p, poly q, const ring r)
1747{
1748  number x, y;
1749
1750  y = pGetCoeff(p);
1751  x = n_Mult(y,pGetCoeff(q),r->cf);
1752  n_Delete(&y,r->cf);
1753  pSetCoeff0(p,x);
1754  //for (int i=pVariables; i!=0; i--)
1755  //{
1756  //  pAddExp(p,i, pGetExp(q,i));
1757  //}
1758  //p->Order += q->Order;
1759  p_ExpVectorAdd(p,q,r);
1760}
1761
1762/*3
1763* compute for monomials p*q
1764* keeps p, q
1765*/
1766static poly p_MonMultC(poly p, poly q, const ring rr)
1767{
1768  number x;
1769  poly r = p_Init(rr);
1770
1771  x = n_Mult(pGetCoeff(p),pGetCoeff(q),rr->cf);
1772  pSetCoeff0(r,x);
1773  p_ExpVectorSum(r,p, q, rr);
1774  return r;
1775}
1776
1777/*3
1778*  create binomial coef.
1779*/
1780static number* pnBin(int exp, const ring r)
1781{
1782  int e, i, h;
1783  number x, y, *bin=NULL;
1784
1785  x = n_Init(exp,r->cf);
1786  if (n_IsZero(x,r->cf))
1787  {
1788    n_Delete(&x,r->cf);
1789    return bin;
1790  }
1791  h = (exp >> 1) + 1;
1792  bin = (number *)omAlloc0(h*sizeof(number));
1793  bin[1] = x;
1794  if (exp < 4)
1795    return bin;
1796  i = exp - 1;
1797  for (e=2; e<h; e++)
1798  {
1799      x = n_Init(i,r->cf);
1800      i--;
1801      y = n_Mult(x,bin[e-1],r->cf);
1802      n_Delete(&x,r->cf);
1803      x = n_Init(e,r->cf);
1804      bin[e] = n_IntDiv(y,x,r->cf);
1805      n_Delete(&x,r->cf);
1806      n_Delete(&y,r->cf);
1807  }
1808  return bin;
1809}
1810
1811static void pnFreeBin(number *bin, int exp,const coeffs r)
1812{
1813  int e, h = (exp >> 1) + 1;
1814
1815  if (bin[1] != NULL)
1816  {
1817    for (e=1; e<h; e++)
1818      n_Delete(&(bin[e]),r);
1819  }
1820  omFreeSize((ADDRESS)bin, h*sizeof(number));
1821}
1822
1823/*
1824*  compute for a poly p = head+tail, tail is monomial
1825*          (head + tail)^exp, exp > 1
1826*          with binomial coef.
1827*/
1828static poly p_TwoMonPower(poly p, int exp, const ring r)
1829{
1830  int eh, e;
1831  long al;
1832  poly *a;
1833  poly tail, b, res, h;
1834  number x;
1835  number *bin = pnBin(exp,r);
1836
1837  tail = pNext(p);
1838  if (bin == NULL)
1839  {
1840    p_MonPower(p,exp,r);
1841    p_MonPower(tail,exp,r);
1842#ifdef PDEBUG
1843    p_Test(p,r);
1844#endif
1845    return p;
1846  }
1847  eh = exp >> 1;
1848  al = (exp + 1) * sizeof(poly);
1849  a = (poly *)omAlloc(al);
1850  a[1] = p;
1851  for (e=1; e<exp; e++)
1852  {
1853    a[e+1] = p_MonMultC(a[e],p,r);
1854  }
1855  res = a[exp];
1856  b = p_Head(tail,r);
1857  for (e=exp-1; e>eh; e--)
1858  {
1859    h = a[e];
1860    x = n_Mult(bin[exp-e],pGetCoeff(h),r->cf);
1861    p_SetCoeff(h,x,r);
1862    p_MonMult(h,b,r);
1863    res = pNext(res) = h;
1864    p_MonMult(b,tail,r);
1865  }
1866  for (e=eh; e!=0; e--)
1867  {
1868    h = a[e];
1869    x = n_Mult(bin[e],pGetCoeff(h),r->cf);
1870    p_SetCoeff(h,x,r);
1871    p_MonMult(h,b,r);
1872    res = pNext(res) = h;
1873    p_MonMult(b,tail,r);
1874  }
1875  p_LmDelete(&tail,r);
1876  pNext(res) = b;
1877  pNext(b) = NULL;
1878  res = a[exp];
1879  omFreeSize((ADDRESS)a, al);
1880  pnFreeBin(bin, exp, r->cf);
1881//  tail=res;
1882// while((tail!=NULL)&&(pNext(tail)!=NULL))
1883// {
1884//   if(nIsZero(pGetCoeff(pNext(tail))))
1885//   {
1886//     pLmDelete(&pNext(tail));
1887//   }
1888//   else
1889//     pIter(tail);
1890// }
1891#ifdef PDEBUG
1892  p_Test(res,r);
1893#endif
1894  return res;
1895}
1896
1897static poly p_Pow(poly p, int i, const ring r)
1898{
1899  poly rc = p_Copy(p,r);
1900  i -= 2;
1901  do
1902  {
1903    rc = p_Mult_q(rc,p_Copy(p,r),r);
1904    p_Normalize(rc,r);
1905    i--;
1906  }
1907  while (i != 0);
1908  return p_Mult_q(rc,p,r);
1909}
1910
1911/*2
1912* returns the i-th power of p
1913* p will be destroyed
1914*/
1915poly p_Power(poly p, int i, const ring r)
1916{
1917  poly rc=NULL;
1918
1919  if (i==0)
1920  {
1921    p_Delete(&p,r);
1922    return p_One(r);
1923  }
1924
1925  if(p!=NULL)
1926  {
1927    if ( (i > 0) && ((unsigned long ) i > (r->bitmask)))
1928    {
1929      Werror("exponent %d is too large, max. is %ld",i,r->bitmask);
1930      return NULL;
1931    }
1932    switch (i)
1933    {
1934// cannot happen, see above
1935//      case 0:
1936//      {
1937//        rc=pOne();
1938//        pDelete(&p);
1939//        break;
1940//      }
1941      case 1:
1942        rc=p;
1943        break;
1944      case 2:
1945        rc=p_Mult_q(p_Copy(p,r),p,r);
1946        break;
1947      default:
1948        if (i < 0)
1949        {
1950          p_Delete(&p,r);
1951          return NULL;
1952        }
1953        else
1954        {
1955#ifdef HAVE_PLURAL
1956          if (rIsPluralRing(r)) /* in the NC case nothing helps :-( */
1957          {
1958            int j=i;
1959            rc = p_Copy(p,r);
1960            while (j>1)
1961            {
1962              rc = p_Mult_q(p_Copy(p,r),rc,r);
1963              j--;
1964            }
1965            p_Delete(&p,r);
1966            return rc;
1967          }
1968#endif
1969          rc = pNext(p);
1970          if (rc == NULL)
1971            return p_MonPower(p,i,r);
1972          /* else: binom ?*/
1973          int char_p=rChar(r);
1974          if ((pNext(rc) != NULL)
1975#ifdef HAVE_RINGS
1976             || rField_is_Ring(r)
1977#endif
1978             )
1979            return p_Pow(p,i,r);
1980          if ((char_p==0) || (i<=char_p))
1981            return p_TwoMonPower(p,i,r);
1982          return p_Pow(p,i,r);
1983        }
1984      /*end default:*/
1985    }
1986  }
1987  return rc;
1988}
1989
1990/* --------------------------------------------------------------------------------*/
1991/* content suff                                                                   */
1992
1993static number p_InitContent(poly ph, const ring r);
1994
1995#define CLEARENUMERATORS 1
1996
1997void p_Content(poly ph, const ring r)
1998{
1999  assume( ph != NULL );
2000
2001  assume( r != NULL ); assume( r->cf != NULL ); 
2002
2003
2004#if CLEARENUMERATORS
2005  if( 0 )
2006  {
2007    const coeffs C = r->cf;
2008      // experimentall (recursive enumerator treatment) of alg. Ext!
2009    CPolyCoeffsEnumerator itr(ph);
2010    n_ClearContent(itr, r->cf);
2011
2012    p_Test(ph, r); n_Test(pGetCoeff(ph), C);
2013    assume(n_GreaterZero(pGetCoeff(ph), C)); // ??
2014
2015      // if(!n_GreaterZero(pGetCoeff(ph),r->cf)) ph = p_Neg(ph,r);
2016    return;
2017  }
2018#endif
2019 
2020 
2021#ifdef HAVE_RINGS
2022  if (rField_is_Ring(r))
2023  {
2024    if (rField_has_Units(r))
2025    {
2026      number k = n_GetUnit(pGetCoeff(ph),r->cf);
2027      if (!n_IsOne(k,r->cf))
2028      {
2029        number tmpGMP = k;
2030        k = n_Invers(k,r->cf);
2031        n_Delete(&tmpGMP,r->cf);
2032        poly h = pNext(ph);
2033        p_SetCoeff(ph, n_Mult(pGetCoeff(ph), k,r->cf),r);
2034        while (h != NULL)
2035        {
2036          p_SetCoeff(h, n_Mult(pGetCoeff(h), k,r->cf),r);
2037          pIter(h);
2038        }
2039//        assume( n_GreaterZero(pGetCoeff(ph),r->cf) );
2040//        if(!n_GreaterZero(pGetCoeff(ph),r->cf)) ph = p_Neg(ph,r);
2041      }
2042      n_Delete(&k,r->cf);
2043    }
2044    return;
2045  }
2046#endif
2047  number h,d;
2048  poly p;
2049
2050  if(TEST_OPT_CONTENTSB) return;
2051  if(pNext(ph)==NULL)
2052  {
2053    p_SetCoeff(ph,n_Init(1,r->cf),r);
2054  }
2055  else
2056  {
2057    assume( pNext(ph) != NULL );
2058#if CLEARENUMERATORS
2059    if( nCoeff_is_Q(r->cf) || nCoeff_is_Q_a(r->cf) )
2060    {
2061      // experimentall (recursive enumerator treatment) of alg. Ext!
2062      CPolyCoeffsEnumerator itr(ph);
2063      n_ClearContent(itr, r->cf);
2064
2065      p_Test(ph, r); n_Test(pGetCoeff(ph), r->cf);
2066      assume(n_GreaterZero(pGetCoeff(ph), r->cf)); // ??
2067     
2068      // if(!n_GreaterZero(pGetCoeff(ph),r->cf)) ph = p_Neg(ph,r);
2069      return;
2070    }
2071#endif
2072   
2073    n_Normalize(pGetCoeff(ph),r->cf);
2074    if(!n_GreaterZero(pGetCoeff(ph),r->cf)) ph = p_Neg(ph,r);
2075    if (rField_is_Q(r)) // should not be used anymore if CLEARENUMERATORS is 1
2076    {
2077      h=p_InitContent(ph,r);
2078      p=ph;
2079    }
2080    else
2081    {
2082      h=n_Copy(pGetCoeff(ph),r->cf);
2083      p = pNext(ph);
2084    }
2085    while (p!=NULL)
2086    {
2087      n_Normalize(pGetCoeff(p),r->cf);
2088      d=n_Gcd(h,pGetCoeff(p),r->cf);
2089      n_Delete(&h,r->cf);
2090      h = d;
2091      if(n_IsOne(h,r->cf))
2092      {
2093        break;
2094      }
2095      pIter(p);
2096    }
2097    p = ph;
2098    //number tmp;
2099    if(!n_IsOne(h,r->cf))
2100    {
2101      while (p!=NULL)
2102      {
2103        //d = nDiv(pGetCoeff(p),h);
2104        //tmp = nIntDiv(pGetCoeff(p),h);
2105        //if (!nEqual(d,tmp))
2106        //{
2107        //  StringSetS("** div0:");nWrite(pGetCoeff(p));StringAppendS("/");
2108        //  nWrite(h);StringAppendS("=");nWrite(d);StringAppendS(" int:");
2109        //  nWrite(tmp);Print(StringEndS("\n"));
2110        //}
2111        //nDelete(&tmp);
2112        d = n_IntDiv(pGetCoeff(p),h,r->cf);
2113        p_SetCoeff(p,d,r);
2114        pIter(p);
2115      }
2116    }
2117    n_Delete(&h,r->cf);
2118#ifdef HAVE_FACTORY
2119//    if ( (n_GetChar(r) == 1) || (n_GetChar(r) < 0) ) /* Q[a],Q(a),Zp[a],Z/p(a) */
2120//    {
2121//      singclap_divide_content(ph, r);
2122//      if(!n_GreaterZero(pGetCoeff(ph),r->cf)) ph = p_Neg(ph,r);
2123//    }
2124#endif
2125    if (rField_is_Q_a(r)) 
2126    {
2127      // we only need special handling for alg. ext.
2128      if (getCoeffType(r->cf)==n_algExt)
2129      {
2130        number hzz = n_Init(1, r->cf->extRing->cf);
2131        p=ph;
2132        while (p!=NULL)
2133        { // each monom: coeff in Q_a
2134          poly c_n_n=(poly)pGetCoeff(p);
2135          poly c_n=c_n_n;
2136          while (c_n!=NULL)
2137          { // each monom: coeff in Q
2138            d=n_Lcm(hzz,pGetCoeff(c_n),r->cf->extRing->cf);
2139            n_Delete(&hzz,r->cf->extRing->cf);
2140            hzz=d;
2141            pIter(c_n);
2142          }
2143          pIter(p);
2144        }
2145        /* hzz contains the 1/lcm of all denominators in c_n_n*/
2146        h=n_Invers(hzz,r->cf->extRing->cf);
2147        n_Delete(&hzz,r->cf->extRing->cf);
2148        n_Normalize(h,r->cf->extRing->cf);
2149        if(!n_IsOne(h,r->cf->extRing->cf))
2150        {
2151          p=ph;
2152          while (p!=NULL)
2153          { // each monom: coeff in Q_a
2154            poly c_n=(poly)pGetCoeff(p);
2155            while (c_n!=NULL)
2156            { // each monom: coeff in Q
2157              d=n_Mult(h,pGetCoeff(c_n),r->cf->extRing->cf);
2158              n_Normalize(d,r->cf->extRing->cf);
2159              n_Delete(&pGetCoeff(c_n),r->cf->extRing->cf);
2160              pGetCoeff(c_n)=d;
2161              pIter(c_n);
2162            }
2163            pIter(p);
2164          }
2165        }
2166        n_Delete(&h,r->cf->extRing->cf);
2167      }
2168    }
2169  }
2170  if(!n_GreaterZero(pGetCoeff(ph),r->cf)) ph = p_Neg(ph,r);
2171}
2172
2173// Not yet?
2174#if 1 // currently only used by Singular/janet
2175void p_SimpleContent(poly ph, int smax, const ring r)
2176{
2177  if(TEST_OPT_CONTENTSB) return;
2178  if (ph==NULL) return;
2179  if (pNext(ph)==NULL)
2180  {
2181    p_SetCoeff(ph,n_Init(1,r->cf),r);
2182    return;
2183  }
2184  if ((pNext(pNext(ph))==NULL)||(!rField_is_Q(r)))
2185  {
2186    return;
2187  }
2188  number d=p_InitContent(ph,r);
2189  if (n_Size(d,r->cf)<=smax)
2190  {
2191    //if (TEST_OPT_PROT) PrintS("G");
2192    return;
2193  }
2194
2195
2196  poly p=ph;
2197  number h=d;
2198  if (smax==1) smax=2;
2199  while (p!=NULL)
2200  {
2201#if 0
2202    d=nlGcd(h,pGetCoeff(p),r->cf);
2203    nlDelete(&h,r->cf);
2204    h = d;
2205#else
2206    nlInpGcd(h,pGetCoeff(p),r->cf);
2207#endif
2208    if(nlSize(h,r->cf)<smax)
2209    {
2210      //if (TEST_OPT_PROT) PrintS("g");
2211      return;
2212    }
2213    pIter(p);
2214  }
2215  p = ph;
2216  if (!nlGreaterZero(pGetCoeff(p),r->cf)) h=nlNeg(h,r->cf);
2217  if(nlIsOne(h,r->cf)) return;
2218  //if (TEST_OPT_PROT) PrintS("c");
2219  while (p!=NULL)
2220  {
2221#if 1
2222    d = nlIntDiv(pGetCoeff(p),h,r->cf);
2223    p_SetCoeff(p,d,r);
2224#else
2225    nlInpIntDiv(pGetCoeff(p),h,r->cf);
2226#endif
2227    pIter(p);
2228  }
2229  nlDelete(&h,r->cf);
2230}
2231#endif
2232
2233static number p_InitContent(poly ph, const ring r)
2234// only for coefficients in Q
2235#if 0
2236{
2237  assume(!TEST_OPT_CONTENTSB);
2238  assume(ph!=NULL);
2239  assume(pNext(ph)!=NULL);
2240  assume(rField_is_Q(r));
2241  if (pNext(pNext(ph))==NULL)
2242  {
2243    return nlGetNom(pGetCoeff(pNext(ph)),r->cf);
2244  }
2245  poly p=ph;
2246  number n1=nlGetNom(pGetCoeff(p),r->cf);
2247  pIter(p);
2248  number n2=nlGetNom(pGetCoeff(p),r->cf);
2249  pIter(p);
2250  number d;
2251  number t;
2252  loop
2253  {
2254    nlNormalize(pGetCoeff(p),r->cf);
2255    t=nlGetNom(pGetCoeff(p),r->cf);
2256    if (nlGreaterZero(t,r->cf))
2257      d=nlAdd(n1,t,r->cf);
2258    else
2259      d=nlSub(n1,t,r->cf);
2260    nlDelete(&t,r->cf);
2261    nlDelete(&n1,r->cf);
2262    n1=d;
2263    pIter(p);
2264    if (p==NULL) break;
2265    nlNormalize(pGetCoeff(p),r->cf);
2266    t=nlGetNom(pGetCoeff(p),r->cf);
2267    if (nlGreaterZero(t,r->cf))
2268      d=nlAdd(n2,t,r->cf);
2269    else
2270      d=nlSub(n2,t,r->cf);
2271    nlDelete(&t,r->cf);
2272    nlDelete(&n2,r->cf);
2273    n2=d;
2274    pIter(p);
2275    if (p==NULL) break;
2276  }
2277  d=nlGcd(n1,n2,r->cf);
2278  nlDelete(&n1,r->cf);
2279  nlDelete(&n2,r->cf);
2280  return d;
2281}
2282#else
2283{
2284  number d=pGetCoeff(ph);
2285  if(SR_HDL(d)&SR_INT) return d;
2286  int s=mpz_size1(d->z);
2287  int s2=-1;
2288  number d2;
2289  loop
2290  {
2291    pIter(ph);
2292    if(ph==NULL)
2293    {
2294      if (s2==-1) return nlCopy(d,r->cf);
2295      break;
2296    }
2297    if (SR_HDL(pGetCoeff(ph))&SR_INT)
2298    {
2299      s2=s;
2300      d2=d;
2301      s=0;
2302      d=pGetCoeff(ph);
2303      if (s2==0) break;
2304    }
2305    else
2306    if (mpz_size1((pGetCoeff(ph)->z))<=s)
2307    {
2308      s2=s;
2309      d2=d;
2310      d=pGetCoeff(ph);
2311      s=mpz_size1(d->z);
2312    }
2313  }
2314  return nlGcd(d,d2,r->cf);
2315}
2316#endif
2317
2318//void pContent(poly ph)
2319//{
2320//  number h,d;
2321//  poly p;
2322//
2323//  p = ph;
2324//  if(pNext(p)==NULL)
2325//  {
2326//    pSetCoeff(p,nInit(1));
2327//  }
2328//  else
2329//  {
2330//#ifdef PDEBUG
2331//    if (!pTest(p)) return;
2332//#endif
2333//    nNormalize(pGetCoeff(p));
2334//    if(!nGreaterZero(pGetCoeff(ph)))
2335//    {
2336//      ph = pNeg(ph);
2337//      nNormalize(pGetCoeff(p));
2338//    }
2339//    h=pGetCoeff(p);
2340//    pIter(p);
2341//    while (p!=NULL)
2342//    {
2343//      nNormalize(pGetCoeff(p));
2344//      if (nGreater(h,pGetCoeff(p))) h=pGetCoeff(p);
2345//      pIter(p);
2346//    }
2347//    h=nCopy(h);
2348//    p=ph;
2349//    while (p!=NULL)
2350//    {
2351//      d=n_Gcd(h,pGetCoeff(p));
2352//      nDelete(&h);
2353//      h = d;
2354//      if(nIsOne(h))
2355//      {
2356//        break;
2357//      }
2358//      pIter(p);
2359//    }
2360//    p = ph;
2361//    //number tmp;
2362//    if(!nIsOne(h))
2363//    {
2364//      while (p!=NULL)
2365//      {
2366//        d = nIntDiv(pGetCoeff(p),h);
2367//        pSetCoeff(p,d);
2368//        pIter(p);
2369//      }
2370//    }
2371//    nDelete(&h);
2372//#ifdef HAVE_FACTORY
2373//    if ( (nGetChar() == 1) || (nGetChar() < 0) ) /* Q[a],Q(a),Zp[a],Z/p(a) */
2374//    {
2375//      pTest(ph);
2376//      singclap_divide_content(ph);
2377//      pTest(ph);
2378//    }
2379//#endif
2380//  }
2381//}
2382#if 0
2383void p_Content(poly ph, const ring r)
2384{
2385  number h,d;
2386  poly p;
2387
2388  if(pNext(ph)==NULL)
2389  {
2390    p_SetCoeff(ph,n_Init(1,r->cf),r);
2391  }
2392  else
2393  {
2394    n_Normalize(pGetCoeff(ph),r->cf);
2395    if(!n_GreaterZero(pGetCoeff(ph),r->cf)) ph = p_Neg(ph,r);
2396    h=n_Copy(pGetCoeff(ph),r->cf);
2397    p = pNext(ph);
2398    while (p!=NULL)
2399    {
2400      n_Normalize(pGetCoeff(p),r->cf);
2401      d=n_Gcd(h,pGetCoeff(p),r->cf);
2402      n_Delete(&h,r->cf);
2403      h = d;
2404      if(n_IsOne(h,r->cf))
2405      {
2406        break;
2407      }
2408      pIter(p);
2409    }
2410    p = ph;
2411    //number tmp;
2412    if(!n_IsOne(h,r->cf))
2413    {
2414      while (p!=NULL)
2415      {
2416        //d = nDiv(pGetCoeff(p),h);
2417        //tmp = nIntDiv(pGetCoeff(p),h);
2418        //if (!nEqual(d,tmp))
2419        //{
2420        //  StringSetS("** div0:");nWrite(pGetCoeff(p));StringAppendS("/");
2421        //  nWrite(h);StringAppendS("=");nWrite(d);StringAppendS(" int:");
2422        //  nWrite(tmp);Print(StringEndS("\n"));
2423        //}
2424        //nDelete(&tmp);
2425        d = n_IntDiv(pGetCoeff(p),h,r->cf);
2426        p_SetCoeff(p,d,r->cf);
2427        pIter(p);
2428      }
2429    }
2430    n_Delete(&h,r->cf);
2431#ifdef HAVE_FACTORY
2432    //if ( (n_GetChar(r) == 1) || (n_GetChar(r) < 0) ) /* Q[a],Q(a),Zp[a],Z/p(a) */
2433    //{
2434    //  singclap_divide_content(ph);
2435    //  if(!n_GreaterZero(pGetCoeff(ph),r)) ph = p_Neg(ph,r);
2436    //}
2437#endif
2438  }
2439}
2440#endif
2441/* ---------------------------------------------------------------------------*/
2442/* cleardenom suff                                                           */
2443poly p_Cleardenom(poly ph, const ring r)
2444{
2445  if( ph == NULL )
2446    return NULL;
2447
2448  assume( r != NULL ); assume( r->cf != NULL ); const coeffs C = r->cf;
2449 
2450#if CLEARENUMERATORS
2451  if( 0 )
2452  {
2453    CPolyCoeffsEnumerator itr(ph);
2454
2455    n_ClearDenominators(itr, C);
2456
2457    n_ClearContent(itr, C); // divide out the content
2458
2459    p_Test(ph, r); n_Test(pGetCoeff(ph), C);
2460    assume(n_GreaterZero(pGetCoeff(ph), C)); // ??
2461//    if(!n_GreaterZero(pGetCoeff(ph),C)) ph = p_Neg(ph,r);
2462
2463    return ph;
2464  }
2465#endif
2466
2467  poly start=ph;
2468
2469  number d, h;
2470  poly p;
2471
2472#ifdef HAVE_RINGS
2473  if (rField_is_Ring(r))
2474  {
2475    p_Content(ph,r);
2476    assume( n_GreaterZero(pGetCoeff(ph),C) );
2477    if(!n_GreaterZero(pGetCoeff(ph),C)) ph = p_Neg(ph,r);
2478    return start;
2479  }
2480#endif
2481
2482  if (rField_is_Zp(r) && TEST_OPT_INTSTRATEGY)
2483  {
2484    assume( n_GreaterZero(pGetCoeff(ph),C) );
2485    if(!n_GreaterZero(pGetCoeff(ph),C)) ph = p_Neg(ph,r);
2486    return start;
2487  }
2488  p = ph;
2489
2490  assume(p != NULL);
2491 
2492  if(pNext(p)==NULL)
2493  {
2494    if (TEST_OPT_CONTENTSB)
2495    {
2496      number n=n_GetDenom(pGetCoeff(p),r->cf);
2497      if (!n_IsOne(n,r->cf))
2498      {
2499        number nn=n_Mult(pGetCoeff(p),n,r->cf);
2500        n_Normalize(nn,r->cf);
2501        p_SetCoeff(p,nn,r);
2502      }
2503      n_Delete(&n,r->cf);
2504    }
2505    else
2506      p_SetCoeff(p,n_Init(1,r->cf),r);
2507
2508    assume( n_GreaterZero(pGetCoeff(ph),C) );
2509    if(!n_GreaterZero(pGetCoeff(ph),C)) ph = p_Neg(ph,r);
2510   
2511    return start;
2512  }
2513
2514  assume(pNext(p)!=NULL);
2515
2516#if CLEARENUMERATORS
2517  if( nCoeff_is_Q(C) || nCoeff_is_Q_a(C) )
2518  {
2519    CPolyCoeffsEnumerator itr(ph);
2520
2521    n_ClearDenominators(itr, C);
2522
2523    n_ClearContent(itr, C); // divide out the content
2524
2525    p_Test(ph, r); n_Test(pGetCoeff(ph), C);
2526    assume(n_GreaterZero(pGetCoeff(ph), C)); // ??
2527//    if(!n_GreaterZero(pGetCoeff(ph),C)) ph = p_Neg(ph,r);
2528   
2529    return start;
2530  }
2531#endif
2532
2533  if(1)
2534  {
2535    h = n_Init(1,r->cf);
2536    while (p!=NULL)
2537    {
2538      n_Normalize(pGetCoeff(p),r->cf);
2539      d=n_Lcm(h,pGetCoeff(p),r->cf);
2540      n_Delete(&h,r->cf);
2541      h=d;
2542      pIter(p);
2543    }
2544    /* contains the 1/lcm of all denominators */
2545    if(!n_IsOne(h,r->cf))
2546    {
2547      p = ph;
2548      while (p!=NULL)
2549      {
2550        /* should be:
2551        * number hh;
2552        * nGetDenom(p->coef,&hh);
2553        * nMult(&h,&hh,&d);
2554        * nNormalize(d);
2555        * nDelete(&hh);
2556        * nMult(d,p->coef,&hh);
2557        * nDelete(&d);
2558        * nDelete(&(p->coef));
2559        * p->coef =hh;
2560        */
2561        d=n_Mult(h,pGetCoeff(p),r->cf);
2562        n_Normalize(d,r->cf);
2563        p_SetCoeff(p,d,r);
2564        pIter(p);
2565      }
2566      n_Delete(&h,r->cf);
2567      if (n_GetChar(r->cf)==1)
2568      {
2569        loop
2570        {
2571          h = n_Init(1,r->cf);
2572          p=ph;
2573          while (p!=NULL)
2574          {
2575            d=n_Lcm(h,pGetCoeff(p),r->cf);
2576            n_Delete(&h,r->cf);
2577            h=d;
2578            pIter(p);
2579          }
2580          /* contains the 1/lcm of all denominators */
2581          if(!n_IsOne(h,r->cf))
2582          {
2583            p = ph;
2584            while (p!=NULL)
2585            {
2586              /* should be:
2587              * number hh;
2588              * nGetDenom(p->coef,&hh);
2589              * nMult(&h,&hh,&d);
2590              * nNormalize(d);
2591              * nDelete(&hh);
2592              * nMult(d,p->coef,&hh);
2593              * nDelete(&d);
2594              * nDelete(&(p->coef));
2595              * p->coef =hh;
2596              */
2597              d=n_Mult(h,pGetCoeff(p),r->cf);
2598              n_Normalize(d,r->cf);
2599              p_SetCoeff(p,d,r);
2600              pIter(p);
2601            }
2602            n_Delete(&h,r->cf);
2603          }
2604          else
2605          {
2606            n_Delete(&h,r->cf);
2607            break;
2608          }
2609        }
2610      }
2611    }
2612    if (h!=NULL) n_Delete(&h,r->cf);
2613
2614    p_Content(ph,r);
2615#ifdef HAVE_RATGRING
2616    if (rIsRatGRing(r))
2617    {
2618      /* quick unit detection in the rational case is done in gr_nc_bba */
2619      pContentRat(ph);
2620      start=ph;
2621    }
2622#endif
2623  }
2624
2625  assume( n_GreaterZero(pGetCoeff(ph),C) );
2626  if(!n_GreaterZero(pGetCoeff(ph),C)) ph = p_Neg(ph,r);
2627 
2628  return start;
2629}
2630
2631void p_Cleardenom_n(poly ph,const ring r,number &c)
2632{
2633  const coeffs C = r->cf;
2634  number d, h;
2635
2636  assume( ph != NULL );
2637
2638  poly p = ph;
2639
2640#if CLEARENUMERATORS
2641  if( 0 )
2642  {
2643    CPolyCoeffsEnumerator itr(ph);
2644
2645    n_ClearDenominators(itr, d, C); // multiply with common denom. d
2646    n_ClearContent(itr, h, C); // divide by the content h
2647
2648    c = n_Div(d, h, C); // d/h
2649
2650    n_Delete(&d, C);
2651    n_Delete(&h, C);
2652
2653    n_Test(c, C);
2654
2655    p_Test(ph, r); n_Test(pGetCoeff(ph), C);
2656    assume(n_GreaterZero(pGetCoeff(ph), C)); // ??
2657/*
2658    if(!n_GreaterZero(pGetCoeff(ph),C))
2659    {
2660      ph = p_Neg(ph,r);
2661      c = n_Neg(c, C);
2662    }
2663*/
2664    return;
2665  }
2666#endif
2667 
2668 
2669  if( pNext(p) == NULL )
2670  {
2671    c=n_Invers(pGetCoeff(p), C);
2672    p_SetCoeff(p, n_Init(1, C), r);
2673
2674    assume( n_GreaterZero(pGetCoeff(ph),C) );
2675    if(!n_GreaterZero(pGetCoeff(ph),C))
2676    {
2677      ph = p_Neg(ph,r);
2678      c = n_Neg(c, C);
2679    }
2680   
2681    return;
2682  }
2683
2684  assume( pNext(p) != NULL );
2685 
2686#if CLEARENUMERATORS
2687  if( nCoeff_is_Q(C) || nCoeff_is_Q_a(C) )
2688  {
2689    CPolyCoeffsEnumerator itr(ph);
2690   
2691    n_ClearDenominators(itr, d, C); // multiply with common denom. d
2692    n_ClearContent(itr, h, C); // divide by the content h
2693
2694    c = n_Div(d, h, C); // d/h
2695
2696    n_Delete(&d, C);
2697    n_Delete(&h, C);
2698
2699    n_Test(c, C);
2700
2701    p_Test(ph, r); n_Test(pGetCoeff(ph), C);
2702    assume(n_GreaterZero(pGetCoeff(ph), C)); // ??
2703/*
2704    if(!n_GreaterZero(pGetCoeff(ph),C))
2705    {
2706      ph = p_Neg(ph,r);
2707      c = n_Neg(c, C);
2708    }
2709*/
2710    return;
2711  }
2712#endif
2713
2714 
2715 
2716
2717  if(1)
2718  {
2719    h = n_Init(1,r->cf);
2720    while (p!=NULL)
2721    {
2722      n_Normalize(pGetCoeff(p),r->cf);
2723      d=n_Lcm(h,pGetCoeff(p),r->cf);
2724      n_Delete(&h,r->cf);
2725      h=d;
2726      pIter(p);
2727    }
2728    c=h;
2729    /* contains the 1/lcm of all denominators */
2730    if(!n_IsOne(h,r->cf))
2731    {
2732      p = ph;
2733      while (p!=NULL)
2734      {
2735        /* should be:
2736        * number hh;
2737        * nGetDenom(p->coef,&hh);
2738        * nMult(&h,&hh,&d);
2739        * nNormalize(d);
2740        * nDelete(&hh);
2741        * nMult(d,p->coef,&hh);
2742        * nDelete(&d);
2743        * nDelete(&(p->coef));
2744        * p->coef =hh;
2745        */
2746        d=n_Mult(h,pGetCoeff(p),r->cf);
2747        n_Normalize(d,r->cf);
2748        p_SetCoeff(p,d,r);
2749        pIter(p);
2750      }
2751      if (rField_is_Q_a(r))
2752      {
2753        loop
2754        {
2755          h = n_Init(1,r->cf);
2756          p=ph;
2757          while (p!=NULL)
2758          {
2759            d=n_Lcm(h,pGetCoeff(p),r->cf);
2760            n_Delete(&h,r->cf);
2761            h=d;
2762            pIter(p);
2763          }
2764          /* contains the 1/lcm of all denominators */
2765          if(!n_IsOne(h,r->cf))
2766          {
2767            p = ph;
2768            while (p!=NULL)
2769            {
2770              /* should be:
2771              * number hh;
2772              * nGetDenom(p->coef,&hh);
2773              * nMult(&h,&hh,&d);
2774              * nNormalize(d);
2775              * nDelete(&hh);
2776              * nMult(d,p->coef,&hh);
2777              * nDelete(&d);
2778              * nDelete(&(p->coef));
2779              * p->coef =hh;
2780              */
2781              d=n_Mult(h,pGetCoeff(p),r->cf);
2782              n_Normalize(d,r->cf);
2783              p_SetCoeff(p,d,r);
2784              pIter(p);
2785            }
2786            number t=n_Mult(c,h,r->cf);
2787            n_Delete(&c,r->cf);
2788            c=t;
2789          }
2790          else
2791          {
2792            break;
2793          }
2794          n_Delete(&h,r->cf);
2795        }
2796      }
2797    }
2798  }
2799
2800  if(!n_GreaterZero(pGetCoeff(ph),C))
2801  {
2802    ph = p_Neg(ph,r);
2803    c = n_Neg(c, C);
2804  }
2805 
2806}
2807
2808number p_GetAllDenom(poly ph, const ring r)
2809{
2810  number d=n_Init(1,r->cf);
2811  poly p = ph;
2812
2813  while (p!=NULL)
2814  {
2815    number h=n_GetDenom(pGetCoeff(p),r->cf);
2816    if (!n_IsOne(h,r->cf))
2817    {
2818      number dd=n_Mult(d,h,r->cf);
2819      n_Delete(&d,r->cf);
2820      d=dd;
2821    }
2822    n_Delete(&h,r->cf);
2823    pIter(p);
2824  }
2825  return d;
2826}
2827
2828int p_Size(poly p, const ring r)
2829{
2830  int count = 0;
2831  while ( p != NULL )
2832  {
2833    count+= n_Size( pGetCoeff( p ), r->cf );
2834    pIter( p );
2835  }
2836  return count;
2837}
2838
2839/*2
2840*make p homogeneous by multiplying the monomials by powers of x_varnum
2841*assume: deg(var(varnum))==1
2842*/
2843poly p_Homogen (poly p, int varnum, const ring r)
2844{
2845  pFDegProc deg;
2846  if (r->pLexOrder && (r->order[0]==ringorder_lp))
2847    deg=p_Totaldegree;
2848  else
2849    deg=r->pFDeg;
2850
2851  poly q=NULL, qn;
2852  int  o,ii;
2853  sBucket_pt bp;
2854
2855  if (p!=NULL)
2856  {
2857    if ((varnum < 1) || (varnum > rVar(r)))
2858    {
2859      return NULL;
2860    }
2861    o=deg(p,r);
2862    q=pNext(p);
2863    while (q != NULL)
2864    {
2865      ii=deg(q,r);
2866      if (ii>o) o=ii;
2867      pIter(q);
2868    }
2869    q = p_Copy(p,r);
2870    bp = sBucketCreate(r);
2871    while (q != NULL)
2872    {
2873      ii = o-deg(q,r);
2874      if (ii!=0)
2875      {
2876        p_AddExp(q,varnum, (long)ii,r);
2877        p_Setm(q,r);
2878      }
2879      qn = pNext(q);
2880      pNext(q) = NULL;
2881      sBucket_Add_p(bp, q, 1);
2882      q = qn;
2883    }
2884    sBucketDestroyAdd(bp, &q, &ii);
2885  }
2886  return q;
2887}
2888
2889/*2
2890*tests if p is homogeneous with respect to the actual weigths
2891*/
2892BOOLEAN p_IsHomogeneous (poly p, const ring r)
2893{
2894  poly qp=p;
2895  int o;
2896
2897  if ((p == NULL) || (pNext(p) == NULL)) return TRUE;
2898  pFDegProc d;
2899  if (r->pLexOrder && (r->order[0]==ringorder_lp))
2900    d=p_Totaldegree;
2901  else
2902    d=r->pFDeg;
2903  o = d(p,r);
2904  do
2905  {
2906    if (d(qp,r) != o) return FALSE;
2907    pIter(qp);
2908  }
2909  while (qp != NULL);
2910  return TRUE;
2911}
2912
2913/*----------utilities for syzygies--------------*/
2914BOOLEAN   p_VectorHasUnitB(poly p, int * k, const ring r)
2915{
2916  poly q=p,qq;
2917  int i;
2918
2919  while (q!=NULL)
2920  {
2921    if (p_LmIsConstantComp(q,r))
2922    {
2923      i = p_GetComp(q,r);
2924      qq = p;
2925      while ((qq != q) && (p_GetComp(qq,r) != i)) pIter(qq);
2926      if (qq == q)
2927      {
2928        *k = i;
2929        return TRUE;
2930      }
2931      else
2932        pIter(q);
2933    }
2934    else pIter(q);
2935  }
2936  return FALSE;
2937}
2938
2939void   p_VectorHasUnit(poly p, int * k, int * len, const ring r)
2940{
2941  poly q=p,qq;
2942  int i,j=0;
2943
2944  *len = 0;
2945  while (q!=NULL)
2946  {
2947    if (p_LmIsConstantComp(q,r))
2948    {
2949      i = p_GetComp(q,r);
2950      qq = p;
2951      while ((qq != q) && (p_GetComp(qq,r) != i)) pIter(qq);
2952      if (qq == q)
2953      {
2954       j = 0;
2955       while (qq!=NULL)
2956       {
2957         if (p_GetComp(qq,r)==i) j++;
2958        pIter(qq);
2959       }
2960       if ((*len == 0) || (j<*len))
2961       {
2962         *len = j;
2963         *k = i;
2964       }
2965      }
2966    }
2967    pIter(q);
2968  }
2969}
2970
2971poly p_TakeOutComp1(poly * p, int k, const ring r)
2972{
2973  poly q = *p;
2974
2975  if (q==NULL) return NULL;
2976
2977  poly qq=NULL,result = NULL;
2978
2979  if (p_GetComp(q,r)==k)
2980  {
2981    result = q; /* *p */
2982    while ((q!=NULL) && (p_GetComp(q,r)==k))
2983    {
2984      p_SetComp(q,0,r);
2985      p_SetmComp(q,r);
2986      qq = q;
2987      pIter(q);
2988    }
2989    *p = q;
2990    pNext(qq) = NULL;
2991  }
2992  if (q==NULL) return result;
2993//  if (pGetComp(q) > k) pGetComp(q)--;
2994  while (pNext(q)!=NULL)
2995  {
2996    if (p_GetComp(pNext(q),r)==k)
2997    {
2998      if (result==NULL)
2999      {
3000        result = pNext(q);
3001        qq = result;
3002      }
3003      else
3004      {
3005        pNext(qq) = pNext(q);
3006        pIter(qq);
3007      }
3008      pNext(q) = pNext(pNext(q));
3009      pNext(qq) =NULL;
3010      p_SetComp(qq,0,r);
3011      p_SetmComp(qq,r);
3012    }
3013    else
3014    {
3015      pIter(q);
3016//      if (pGetComp(q) > k) pGetComp(q)--;
3017    }
3018  }
3019  return result;
3020}
3021
3022poly p_TakeOutComp(poly * p, int k, const ring r)
3023{
3024  poly q = *p,qq=NULL,result = NULL;
3025
3026  if (q==NULL) return NULL;
3027  BOOLEAN use_setmcomp=rOrd_SetCompRequiresSetm(r);
3028  if (p_GetComp(q,r)==k)
3029  {
3030    result = q;
3031    do
3032    {
3033      p_SetComp(q,0,r);
3034      if (use_setmcomp) p_SetmComp(q,r);
3035      qq = q;
3036      pIter(q);
3037    }
3038    while ((q!=NULL) && (p_GetComp(q,r)==k));
3039    *p = q;
3040    pNext(qq) = NULL;
3041  }
3042  if (q==NULL) return result;
3043  if (p_GetComp(q,r) > k)
3044  {
3045    p_SubComp(q,1,r);
3046    if (use_setmcomp) p_SetmComp(q,r);
3047  }
3048  poly pNext_q;
3049  while ((pNext_q=pNext(q))!=NULL)
3050  {
3051    if (p_GetComp(pNext_q,r)==k)
3052    {
3053      if (result==NULL)
3054      {
3055        result = pNext_q;
3056        qq = result;
3057      }
3058      else
3059      {
3060        pNext(qq) = pNext_q;
3061        pIter(qq);
3062      }
3063      pNext(q) = pNext(pNext_q);
3064      pNext(qq) =NULL;
3065      p_SetComp(qq,0,r);
3066      if (use_setmcomp) p_SetmComp(qq,r);
3067    }
3068    else
3069    {
3070      /*pIter(q);*/ q=pNext_q;
3071      if (p_GetComp(q,r) > k)
3072      {
3073        p_SubComp(q,1,r);
3074        if (use_setmcomp) p_SetmComp(q,r);
3075      }
3076    }
3077  }
3078  return result;
3079}
3080
3081// Splits *p into two polys: *q which consists of all monoms with
3082// component == comp and *p of all other monoms *lq == pLength(*q)
3083void p_TakeOutComp(poly *r_p, long comp, poly *r_q, int *lq, const ring r)
3084{
3085  spolyrec pp, qq;
3086  poly p, q, p_prev;
3087  int l = 0;
3088
3089#ifdef HAVE_ASSUME
3090  int lp = pLength(*r_p);
3091#endif
3092
3093  pNext(&pp) = *r_p;
3094  p = *r_p;
3095  p_prev = &pp;
3096  q = &qq;
3097
3098  while(p != NULL)
3099  {
3100    while (p_GetComp(p,r) == comp)
3101    {
3102      pNext(q) = p;
3103      pIter(q);
3104      p_SetComp(p, 0,r);
3105      p_SetmComp(p,r);
3106      pIter(p);
3107      l++;
3108      if (p == NULL)
3109      {
3110        pNext(p_prev) = NULL;
3111        goto Finish;
3112      }
3113    }
3114    pNext(p_prev) = p;
3115    p_prev = p;
3116    pIter(p);
3117  }
3118
3119  Finish:
3120  pNext(q) = NULL;
3121  *r_p = pNext(&pp);
3122  *r_q = pNext(&qq);
3123  *lq = l;
3124#ifdef HAVE_ASSUME
3125  assume(pLength(*r_p) + pLength(*r_q) == lp);
3126#endif
3127  p_Test(*r_p,r);
3128  p_Test(*r_q,r);
3129}
3130
3131void p_DeleteComp(poly * p,int k, const ring r)
3132{
3133  poly q;
3134
3135  while ((*p!=NULL) && (p_GetComp(*p,r)==k)) p_LmDelete(p,r);
3136  if (*p==NULL) return;
3137  q = *p;
3138  if (p_GetComp(q,r)>k)
3139  {
3140    p_SubComp(q,1,r);
3141    p_SetmComp(q,r);
3142  }
3143  while (pNext(q)!=NULL)
3144  {
3145    if (p_GetComp(pNext(q),r)==k)
3146      p_LmDelete(&(pNext(q)),r);
3147    else
3148    {
3149      pIter(q);
3150      if (p_GetComp(q,r)>k)
3151      {
3152        p_SubComp(q,1,r);
3153        p_SetmComp(q,r);
3154      }
3155    }
3156  }
3157}
3158
3159/*2
3160* convert a vector to a set of polys,
3161* allocates the polyset, (entries 0..(*len)-1)
3162* the vector will not be changed
3163*/
3164void  p_Vec2Polys(poly v, poly* *p, int *len, const ring r)
3165{
3166  poly h;
3167  int k;
3168
3169  *len=p_MaxComp(v,r);
3170  if (*len==0) *len=1;
3171  *p=(poly*)omAlloc0((*len)*sizeof(poly));
3172  while (v!=NULL)
3173  {
3174    h=p_Head(v,r);
3175    k=p_GetComp(h,r);
3176    p_SetComp(h,0,r);
3177    (*p)[k-1]=p_Add_q((*p)[k-1],h,r);
3178    pIter(v);
3179  }
3180}
3181
3182//
3183// resets the pFDeg and pLDeg: if pLDeg is not given, it is
3184// set to currRing->pLDegOrig, i.e. to the respective LDegProc which
3185// only uses pFDeg (and not p_Deg, or pTotalDegree, etc)
3186void pSetDegProcs(ring r, pFDegProc new_FDeg, pLDegProc new_lDeg)
3187{
3188  assume(new_FDeg != NULL);
3189  r->pFDeg = new_FDeg;
3190
3191  if (new_lDeg == NULL)
3192    new_lDeg = r->pLDegOrig;
3193
3194  r->pLDeg = new_lDeg;
3195}
3196
3197// restores pFDeg and pLDeg:
3198void pRestoreDegProcs(ring r, pFDegProc old_FDeg, pLDegProc old_lDeg)
3199{
3200  assume(old_FDeg != NULL && old_lDeg != NULL);
3201  r->pFDeg = old_FDeg;
3202  r->pLDeg = old_lDeg;
3203}
3204
3205/*-------- several access procedures to monomials -------------------- */
3206/*
3207* the module weights for std
3208*/
3209static pFDegProc pOldFDeg;
3210static pLDegProc pOldLDeg;
3211static BOOLEAN pOldLexOrder;
3212
3213static long pModDeg(poly p, ring r)
3214{
3215  long d=pOldFDeg(p, r);
3216  int c=p_GetComp(p, r);
3217  if ((c>0) && ((r->pModW)->range(c-1))) d+= (*(r->pModW))[c-1];
3218  return d;
3219  //return pOldFDeg(p, r)+(*pModW)[p_GetComp(p, r)-1];
3220}
3221
3222void p_SetModDeg(intvec *w, ring r)
3223{
3224  if (w!=NULL)
3225  {
3226    r->pModW = w;
3227    pOldFDeg = r->pFDeg;
3228    pOldLDeg = r->pLDeg;
3229    pOldLexOrder = r->pLexOrder;
3230    pSetDegProcs(r,pModDeg);
3231    r->pLexOrder = TRUE;
3232  }
3233  else
3234  {
3235    r->pModW = NULL;
3236    pRestoreDegProcs(r,pOldFDeg, pOldLDeg);
3237    r->pLexOrder = pOldLexOrder;
3238  }
3239}
3240
3241/*2
3242* handle memory request for sets of polynomials (ideals)
3243* l is the length of *p, increment is the difference (may be negative)
3244*/
3245void pEnlargeSet(poly* *p, int l, int increment)
3246{
3247  poly* h;
3248
3249  h=(poly*)omReallocSize((poly*)*p,l*sizeof(poly),(l+increment)*sizeof(poly));
3250  if (increment>0)
3251  {
3252    //for (i=l; i<l+increment; i++)
3253    //  h[i]=NULL;
3254    memset(&(h[l]),0,increment*sizeof(poly));
3255  }
3256  *p=h;
3257}
3258
3259/*2
3260*divides p1 by its leading coefficient
3261*/
3262void p_Norm(poly p1, const ring r)
3263{
3264#ifdef HAVE_RINGS
3265  if (rField_is_Ring(r))
3266  {
3267    if (!n_IsUnit(pGetCoeff(p1), r->cf)) return;
3268    // Werror("p_Norm not possible in the case of coefficient rings.");
3269  }
3270  else
3271#endif
3272  if (p1!=NULL)
3273  {
3274    if (pNext(p1)==NULL)
3275    {
3276      p_SetCoeff(p1,n_Init(1,r->cf),r);
3277      return;
3278    }
3279    poly h;
3280    if (!n_IsOne(pGetCoeff(p1),r->cf))
3281    {
3282      number k, c;
3283      n_Normalize(pGetCoeff(p1),r->cf);
3284      k = pGetCoeff(p1);
3285      c = n_Init(1,r->cf);
3286      pSetCoeff0(p1,c);
3287      h = pNext(p1);
3288      while (h!=NULL)
3289      {
3290        c=n_Div(pGetCoeff(h),k,r->cf);
3291        // no need to normalize: Z/p, R
3292        // normalize already in nDiv: Q_a, Z/p_a
3293        // remains: Q
3294        if (rField_is_Q(r) && (!n_IsOne(c,r->cf))) n_Normalize(c,r->cf);
3295        p_SetCoeff(h,c,r);
3296        pIter(h);
3297      }
3298      n_Delete(&k,r->cf);
3299    }
3300    else
3301    {
3302      //if (r->cf->cfNormalize != nDummy2) //TODO: OPTIMIZE
3303      {
3304        h = pNext(p1);
3305        while (h!=NULL)
3306        {
3307          n_Normalize(pGetCoeff(h),r->cf);
3308          pIter(h);
3309        }
3310      }
3311    }
3312  }
3313}
3314
3315/*2
3316*normalize all coefficients
3317*/
3318void p_Normalize(poly p,const ring r)
3319{
3320  if (rField_has_simple_inverse(r)) return; /* Z/p, GF(p,n), R, long R/C */
3321  while (p!=NULL)
3322  {
3323#ifdef LDEBUG
3324    n_Test(pGetCoeff(p), r->cf);
3325#endif
3326    n_Normalize(pGetCoeff(p),r->cf);
3327    pIter(p);
3328  }
3329}
3330
3331// splits p into polys with Exp(n) == 0 and Exp(n) != 0
3332// Poly with Exp(n) != 0 is reversed
3333static void p_SplitAndReversePoly(poly p, int n, poly *non_zero, poly *zero, const ring r)
3334{
3335  if (p == NULL)
3336  {
3337    *non_zero = NULL;
3338    *zero = NULL;
3339    return;
3340  }
3341  spolyrec sz;
3342  poly z, n_z, next;
3343  z = &sz;
3344  n_z = NULL;
3345
3346  while(p != NULL)
3347  {
3348    next = pNext(p);
3349    if (p_GetExp(p, n,r) == 0)
3350    {
3351      pNext(z) = p;
3352      pIter(z);
3353    }
3354    else
3355    {
3356      pNext(p) = n_z;
3357      n_z = p;
3358    }
3359    p = next;
3360  }
3361  pNext(z) = NULL;
3362  *zero = pNext(&sz);
3363  *non_zero = n_z;
3364}
3365/*3
3366* substitute the n-th variable by 1 in p
3367* destroy p
3368*/
3369static poly p_Subst1 (poly p,int n, const ring r)
3370{
3371  poly qq=NULL, result = NULL;
3372  poly zero=NULL, non_zero=NULL;
3373
3374  // reverse, so that add is likely to be linear
3375  p_SplitAndReversePoly(p, n, &non_zero, &zero,r);
3376
3377  while (non_zero != NULL)
3378  {
3379    assume(p_GetExp(non_zero, n,r) != 0);
3380    qq = non_zero;
3381    pIter(non_zero);
3382    qq->next = NULL;
3383    p_SetExp(qq,n,0,r);
3384    p_Setm(qq,r);
3385    result = p_Add_q(result,qq,r);
3386  }
3387  p = p_Add_q(result, zero,r);
3388  p_Test(p,r);
3389  return p;
3390}
3391
3392/*3
3393* substitute the n-th variable by number e in p
3394* destroy p
3395*/
3396static poly p_Subst2 (poly p,int n, number e, const ring r)
3397{
3398  assume( ! n_IsZero(e,r->cf) );
3399  poly qq,result = NULL;
3400  number nn, nm;
3401  poly zero, non_zero;
3402
3403  // reverse, so that add is likely to be linear
3404  p_SplitAndReversePoly(p, n, &non_zero, &zero,r);
3405
3406  while (non_zero != NULL)
3407  {
3408    assume(p_GetExp(non_zero, n, r) != 0);
3409    qq = non_zero;
3410    pIter(non_zero);
3411    qq->next = NULL;
3412    n_Power(e, p_GetExp(qq, n, r), &nn,r->cf);
3413    nm = n_Mult(nn, pGetCoeff(qq),r->cf);
3414#ifdef HAVE_RINGS
3415    if (n_IsZero(nm,r->cf))
3416    {
3417      p_LmFree(&qq,r);
3418      n_Delete(&nm,r->cf);
3419    }
3420    else
3421#endif
3422    {
3423      p_SetCoeff(qq, nm,r);
3424      p_SetExp(qq, n, 0,r);
3425      p_Setm(qq,r);
3426      result = p_Add_q(result,qq,r);
3427    }
3428    n_Delete(&nn,r->cf);
3429  }
3430  p = p_Add_q(result, zero,r);
3431  p_Test(p,r);
3432  return p;
3433}
3434
3435
3436/* delete monoms whose n-th exponent is different from zero */
3437static poly p_Subst0(poly p, int n, const ring r)
3438{
3439  spolyrec res;
3440  poly h = &res;
3441  pNext(h) = p;
3442
3443  while (pNext(h)!=NULL)
3444  {
3445    if (p_GetExp(pNext(h),n,r)!=0)
3446    {
3447      p_LmDelete(&pNext(h),r);
3448    }
3449    else
3450    {
3451      pIter(h);
3452    }
3453  }
3454  p_Test(pNext(&res),r);
3455  return pNext(&res);
3456}
3457
3458/*2
3459* substitute the n-th variable by e in p
3460* destroy p
3461*/
3462poly p_Subst(poly p, int n, poly e, const ring r)
3463{
3464  if (e == NULL) return p_Subst0(p, n,r);
3465
3466  if (p_IsConstant(e,r))
3467  {
3468    if (n_IsOne(pGetCoeff(e),r->cf)) return p_Subst1(p,n,r);
3469    else return p_Subst2(p, n, pGetCoeff(e),r);
3470  }
3471
3472#ifdef HAVE_PLURAL
3473  if (rIsPluralRing(r))
3474  {
3475    return nc_pSubst(p,n,e,r);
3476  }
3477#endif
3478
3479  int exponent,i;
3480  poly h, res, m;
3481  int *me,*ee;
3482  number nu,nu1;
3483
3484  me=(int *)omAlloc((rVar(r)+1)*sizeof(int));
3485  ee=(int *)omAlloc((rVar(r)+1)*sizeof(int));
3486  if (e!=NULL) p_GetExpV(e,ee,r);
3487  res=NULL;
3488  h=p;
3489  while (h!=NULL)
3490  {
3491    if ((e!=NULL) || (p_GetExp(h,n,r)==0))
3492    {
3493      m=p_Head(h,r);
3494      p_GetExpV(m,me,r);
3495      exponent=me[n];
3496      me[n]=0;
3497      for(i=rVar(r);i>0;i--)
3498        me[i]+=exponent*ee[i];
3499      p_SetExpV(m,me,r);
3500      if (e!=NULL)
3501      {
3502        n_Power(pGetCoeff(e),exponent,&nu,r->cf);
3503        nu1=n_Mult(pGetCoeff(m),nu,r->cf);
3504        n_Delete(&nu,r->cf);
3505        p_SetCoeff(m,nu1,r);
3506      }
3507      res=p_Add_q(res,m,r);
3508    }
3509    p_LmDelete(&h,r);
3510  }
3511  omFreeSize((ADDRESS)me,(rVar(r)+1)*sizeof(int));
3512  omFreeSize((ADDRESS)ee,(rVar(r)+1)*sizeof(int));
3513  return res;
3514}
3515
3516/*2
3517 * returns a re-ordered convertion of a number as a polynomial,
3518 * with permutation of parameters
3519 * NOTE: this only works for Frank's alg. & trans. fields
3520 */
3521poly n_PermNumber(const number z, const int *par_perm, const int , const ring src, const ring dst)
3522{
3523#if 0
3524  PrintS("\nSource Ring: \n");
3525  rWrite(src);
3526
3527  if(0)
3528  {
3529    number zz = n_Copy(z, src->cf);
3530    PrintS("z: "); n_Write(zz, src);
3531    n_Delete(&zz, src->cf);
3532  }
3533
3534  PrintS("\nDestination Ring: \n");
3535  rWrite(dst);
3536
3537  Print("\nOldPar: %d\n", OldPar);
3538  for( int i = 1; i <= OldPar; i++ )
3539  {
3540    Print("par(%d) -> par/var (%d)\n", i, par_perm[i-1]);
3541  }
3542#endif
3543  if( z == NULL )
3544     return NULL;
3545
3546  const coeffs srcCf = src->cf;
3547  assume( srcCf != NULL );
3548
3549  assume( !nCoeff_is_GF(srcCf) );
3550  assume( rField_is_Extension(src) );
3551
3552  poly zz = NULL;
3553
3554  const ring srcExtRing = srcCf->extRing;
3555  assume( srcExtRing != NULL );
3556
3557  const coeffs dstCf = dst->cf;
3558  assume( dstCf != NULL );
3559
3560  if( nCoeff_is_algExt(srcCf) ) // nCoeff_is_GF(srcCf)?
3561  {
3562    zz = (poly) z;
3563
3564    if( zz == NULL )
3565       return NULL;
3566
3567  } else if (nCoeff_is_transExt(srcCf))
3568  {
3569    assume( !IS0(z) );
3570
3571    zz = NUM(z);
3572    p_Test (zz, srcExtRing);
3573
3574    if( zz == NULL )
3575       return NULL;
3576
3577    //if( !DENIS1(z) )
3578      //WarnS("Not implemented yet: Cannot permute a rational fraction and make a polynomial out of it! Ignorring the denumerator.");
3579  } else
3580     {
3581        assume (FALSE);
3582        Werror("Number permutation is not implemented for this data yet!");
3583        return NULL;
3584     }
3585
3586  assume( zz != NULL );
3587  p_Test (zz, srcExtRing);
3588
3589
3590  nMapFunc nMap = n_SetMap(srcExtRing->cf, dstCf);
3591
3592  assume( nMap != NULL );
3593
3594  poly qq = p_PermPoly(zz, par_perm - 1, srcExtRing, dst, nMap, NULL, rVar(srcExtRing) );
3595//       poly p_PermPoly (poly p, int * perm, const ring oldRing, const ring dst, nMapFunc nMap, int *par_perm, int OldPar)
3596
3597//  assume( FALSE );  WarnS("longalg missing 2");
3598
3599  return qq;
3600}
3601
3602
3603/*2
3604*returns a re-ordered copy of a polynomial, with permutation of the variables
3605*/
3606poly p_PermPoly (poly p, const int * perm, const ring oldRing, const ring dst,
3607       nMapFunc nMap, const int *par_perm, int OldPar)
3608{
3609#if 0
3610    p_Test(p, oldRing);
3611    PrintS("\np_PermPoly::p: "); p_Write(p, oldRing, oldRing); PrintLn();
3612#endif
3613
3614  const int OldpVariables = rVar(oldRing);
3615  poly result = NULL;
3616  poly result_last = NULL;
3617  poly aq = NULL; /* the map coefficient */
3618  poly qq; /* the mapped monomial */
3619
3620  assume(dst != NULL);
3621  assume(dst->cf != NULL);
3622 
3623  while (p != NULL)
3624  {
3625    // map the coefficient
3626    if ( ((OldPar == 0) || (par_perm == NULL) || rField_is_GF(oldRing)) && (nMap != NULL) )
3627    {
3628      qq = p_Init(dst);
3629      assume( nMap != NULL );
3630      number n = nMap(p_GetCoeff(p, oldRing), oldRing->cf, dst->cf);
3631
3632      if ( nCoeff_is_algExt(dst->cf) )
3633        n_Normalize(n, dst->cf);
3634
3635      p_GetCoeff(qq, dst) = n;// Note: n can be a ZERO!!!
3636      // coef may be zero: 
3637//      p_Test(qq, dst);
3638    }
3639    else
3640    {
3641      qq = p_One(dst);
3642
3643//      aq = naPermNumber(p_GetCoeff(p, oldRing), par_perm, OldPar, oldRing); // no dst???
3644//      poly    n_PermNumber(const number z, const int *par_perm, const int P, const ring src, const ring dst)
3645      aq = n_PermNumber(p_GetCoeff(p, oldRing), par_perm, OldPar, oldRing, dst);
3646
3647      p_Test(aq, dst);
3648
3649      if ( nCoeff_is_algExt(dst->cf) )
3650        p_Normalize(aq,dst);
3651     
3652      if (aq == NULL)
3653        p_SetCoeff(qq, n_Init(0, dst->cf),dst); // Very dirty trick!!!
3654
3655      p_Test(aq, dst);
3656    }
3657
3658    if (rRing_has_Comp(dst))
3659       p_SetComp(qq, p_GetComp(p, oldRing), dst);
3660
3661    if ( n_IsZero(pGetCoeff(qq), dst->cf) )
3662    {
3663      p_LmDelete(&qq,dst);
3664      qq = NULL;
3665    }
3666    else
3667    {
3668      // map pars:
3669      int mapped_to_par = 0;
3670      for(int i = 1; i <= OldpVariables; i++)
3671      {
3672        int e = p_GetExp(p, i, oldRing);
3673        if (e != 0)
3674        {
3675          if (perm==NULL)
3676            p_SetExp(qq, i, e, dst);
3677          else if (perm[i]>0)
3678            p_AddExp(qq,perm[i], e/*p_GetExp( p,i,oldRing)*/, dst);
3679          else if (perm[i]<0)
3680          {
3681            number c = p_GetCoeff(qq, dst);
3682            if (rField_is_GF(dst))
3683            {
3684              assume( dst->cf->extRing == NULL );
3685              number ee = n_Param(1, dst);
3686
3687              number eee;
3688              n_Power(ee, e, &eee, dst->cf); //nfDelete(ee,dst);
3689
3690              ee = n_Mult(c, eee, dst->cf);
3691              //nfDelete(c,dst);nfDelete(eee,dst);
3692              pSetCoeff0(qq,ee);
3693            }
3694            else if (nCoeff_is_Extension(dst->cf))
3695            {
3696              const int par = -perm[i];
3697              assume( par > 0 );
3698
3699//              WarnS("longalg missing 3");
3700#if 1
3701              const coeffs C = dst->cf;
3702              assume( C != NULL );
3703
3704              const ring R = C->extRing;
3705              assume( R != NULL );
3706
3707              assume( par <= rVar(R) );
3708
3709              poly pcn; // = (number)c
3710
3711              assume( !n_IsZero(c, C) );
3712
3713              if( nCoeff_is_algExt(C) )
3714                 pcn = (poly) c;
3715               else //            nCoeff_is_transExt(C)
3716                 pcn = NUM(c);
3717
3718              if (pNext(pcn) == NULL) // c->z
3719                p_AddExp(pcn, -perm[i], e, R);
3720              else /* more difficult: we have really to multiply: */
3721              {
3722                poly mmc = p_ISet(1, R);
3723                p_SetExp(mmc, -perm[i], e, R);
3724                p_Setm(mmc, R);
3725
3726                number nnc;
3727                // convert back to a number: number nnc = mmc;
3728                if( nCoeff_is_algExt(C) )
3729                   nnc = (number) mmc;
3730                else //            nCoeff_is_transExt(C)
3731                  nnc = ntInit(mmc, C);
3732
3733                p_GetCoeff(qq, dst) = n_Mult((number)c, nnc, C);
3734                n_Delete((number *)&c, C);
3735                n_Delete((number *)&nnc, C);
3736              }
3737
3738              mapped_to_par=1;
3739#endif
3740            }
3741          }
3742          else
3743          {
3744            /* this variable maps to 0 !*/
3745            p_LmDelete(&qq, dst);
3746            break;
3747          }
3748        }
3749      }
3750      if ( mapped_to_par && nCoeff_is_algExt(dst->cf) )
3751      {
3752        number n = p_GetCoeff(qq, dst);
3753        n_Normalize(n, dst->cf);
3754        p_GetCoeff(qq, dst) = n;
3755      }
3756    }
3757    pIter(p);
3758
3759#if 0
3760    p_Test(aq,dst);
3761    PrintS("\naq: "); p_Write(aq, dst, dst); PrintLn();
3762#endif
3763
3764
3765#if 1
3766    if (qq!=NULL)
3767    {
3768      p_Setm(qq,dst);
3769
3770      p_Test(aq,dst);
3771      p_Test(qq,dst);
3772
3773#if 0
3774    p_Test(qq,dst);
3775    PrintS("\nqq: "); p_Write(qq, dst, dst); PrintLn();
3776#endif
3777
3778      if (aq!=NULL)
3779         qq=p_Mult_q(aq,qq,dst);
3780
3781      aq = qq;
3782
3783      while (pNext(aq) != NULL) pIter(aq);
3784
3785      if (result_last==NULL)
3786      {
3787        result=qq;
3788      }
3789      else
3790      {
3791        pNext(result_last)=qq;
3792      }
3793      result_last=aq;
3794      aq = NULL;
3795    }
3796    else if (aq!=NULL)
3797    {
3798      p_Delete(&aq,dst);
3799    }
3800  }
3801
3802  result=p_SortAdd(result,dst);
3803#else
3804  //  if (qq!=NULL)
3805  //  {
3806  //    pSetm(qq);
3807  //    pTest(qq);
3808  //    pTest(aq);
3809  //    if (aq!=NULL) qq=pMult(aq,qq);
3810  //    aq = qq;
3811  //    while (pNext(aq) != NULL) pIter(aq);
3812  //    pNext(aq) = result;
3813  //    aq = NULL;
3814  //    result = qq;
3815  //  }
3816  //  else if (aq!=NULL)
3817  //  {
3818  //    pDelete(&aq);
3819  //  }
3820  //}
3821  //p = result;
3822  //result = NULL;
3823  //while (p != NULL)
3824  //{
3825  //  qq = p;
3826  //  pIter(p);
3827  //  qq->next = NULL;
3828  //  result = pAdd(result, qq);
3829  //}
3830#endif
3831  p_Test(result,dst);
3832
3833#if 0
3834  p_Test(result,dst);
3835  PrintS("\nresult: "); p_Write(result,dst,dst); PrintLn();
3836#endif
3837  return result;
3838}
3839/**************************************************************
3840 *
3841 * Jet
3842 *
3843 **************************************************************/
3844
3845poly pp_Jet(poly p, int m, const ring R)
3846{
3847  poly r=NULL;
3848  poly t=NULL;
3849
3850  while (p!=NULL)
3851  {
3852    if (p_Totaldegree(p,R)<=m)
3853    {
3854      if (r==NULL)
3855        r=p_Head(p,R);
3856      else
3857      if (t==NULL)
3858      {
3859        pNext(r)=p_Head(p,R);
3860        t=pNext(r);
3861      }
3862      else
3863      {
3864        pNext(t)=p_Head(p,R);
3865        pIter(t);
3866      }
3867    }
3868    pIter(p);
3869  }
3870  return r;
3871}
3872
3873poly p_Jet(poly p, int m,const ring R)
3874{
3875  while((p!=NULL) && (p_Totaldegree(p,R)>m)) p_LmDelete(&p,R);
3876  if (p==NULL) return NULL;
3877  poly r=p;
3878  while (pNext(p)!=NULL)
3879  {
3880    if (p_Totaldegree(pNext(p),R)>m)
3881    {
3882      p_LmDelete(&pNext(p),R);
3883    }
3884    else
3885      pIter(p);
3886  }
3887  return r;
3888}
3889
3890poly pp_JetW(poly p, int m, short *w, const ring R)
3891{
3892  poly r=NULL;
3893  poly t=NULL;
3894  while (p!=NULL)
3895  {
3896    if (totaldegreeWecart_IV(p,R,w)<=m)
3897    {
3898      if (r==NULL)
3899        r=p_Head(p,R);
3900      else
3901      if (t==NULL)
3902      {
3903        pNext(r)=p_Head(p,R);
3904        t=pNext(r);
3905      }
3906      else
3907      {
3908        pNext(t)=p_Head(p,R);
3909        pIter(t);
3910      }
3911    }
3912    pIter(p);
3913  }
3914  return r;
3915}
3916
3917poly p_JetW(poly p, int m, short *w, const ring R)
3918{
3919  while((p!=NULL) && (totaldegreeWecart_IV(p,R,w)>m)) p_LmDelete(&p,R);
3920  if (p==NULL) return NULL;
3921  poly r=p;
3922  while (pNext(p)!=NULL)
3923  {
3924    if (totaldegreeWecart_IV(pNext(p),R,w)>m)
3925    {
3926      p_LmDelete(&pNext(p),R);
3927    }
3928    else
3929      pIter(p);
3930  }
3931  return r;
3932}
3933
3934/*************************************************************/
3935int p_MinDeg(poly p,intvec *w, const ring R)
3936{
3937  if(p==NULL)
3938    return -1;
3939  int d=-1;
3940  while(p!=NULL)
3941  {
3942    int d0=0;
3943    for(int j=0;j<rVar(R);j++)
3944      if(w==NULL||j>=w->length())
3945        d0+=p_GetExp(p,j+1,R);
3946      else
3947        d0+=(*w)[j]*p_GetExp(p,j+1,R);
3948    if(d0<d||d==-1)
3949      d=d0;
3950    pIter(p);
3951  }
3952  return d;
3953}
3954
3955/***************************************************************/
3956
3957poly p_Series(int n,poly p,poly u, intvec *w, const ring R)
3958{
3959  short *ww=iv2array(w,R);
3960  if(p!=NULL)
3961  {
3962    if(u==NULL)
3963      p=p_JetW(p,n,ww,R);
3964    else
3965      p=p_JetW(p_Mult_q(p,p_Invers(n-p_MinDeg(p,w,R),u,w,R),R),n,ww,R);
3966  }
3967  omFreeSize((ADDRESS)ww,(rVar(R)+1)*sizeof(short));
3968  return p;
3969}
3970
3971poly p_Invers(int n,poly u,intvec *w, const ring R)
3972{
3973  if(n<0)
3974    return NULL;
3975  number u0=n_Invers(pGetCoeff(u),R->cf);
3976  poly v=p_NSet(u0,R);
3977  if(n==0)
3978    return v;
3979  short *ww=iv2array(w,R);
3980  poly u1=p_JetW(p_Sub(p_One(R),p_Mult_nn(u,u0,R),R),n,ww,R);
3981  if(u1==NULL)
3982  {
3983    omFreeSize((ADDRESS)ww,(rVar(R)+1)*sizeof(short));
3984    return v;
3985  }
3986  poly v1=p_Mult_nn(p_Copy(u1,R),u0,R);
3987  v=p_Add_q(v,p_Copy(v1,R),R);
3988  for(int i=n/p_MinDeg(u1,w,R);i>1;i--)
3989  {
3990    v1=p_JetW(p_Mult_q(v1,p_Copy(u1,R),R),n,ww,R);
3991    v=p_Add_q(v,p_Copy(v1,R),R);
3992  }
3993  p_Delete(&u1,R);
3994  p_Delete(&v1,R);
3995  omFreeSize((ADDRESS)ww,(rVar(R)+1)*sizeof(short));
3996  return v;
3997}
3998
3999BOOLEAN p_EqualPolys(poly p1,poly p2, const ring r)
4000{
4001  while ((p1 != NULL) && (p2 != NULL))
4002  {
4003    if (! p_LmEqual(p1, p2,r))
4004      return FALSE;
4005    if (! n_Equal(p_GetCoeff(p1,r), p_GetCoeff(p2,r),r->cf ))
4006      return FALSE;
4007    pIter(p1);
4008    pIter(p2);
4009  }
4010  return (p1==p2);
4011}
4012
4013static inline BOOLEAN p_ExpVectorEqual(poly p1, poly p2, const ring r1, const ring r2)
4014{
4015  assume( r1 == r2 || rSamePolyRep(r1, r2) );
4016
4017  p_LmCheckPolyRing1(p1, r1);
4018  p_LmCheckPolyRing1(p2, r2);
4019
4020  int i = r1->ExpL_Size;
4021
4022  assume( r1->ExpL_Size == r2->ExpL_Size );
4023
4024  unsigned long *ep = p1->exp;
4025  unsigned long *eq = p2->exp;
4026
4027  do
4028  {
4029    i--;
4030    if (ep[i] != eq[i]) return FALSE;
4031  }
4032  while (i);
4033
4034  return TRUE;
4035}
4036
4037BOOLEAN p_EqualPolys(poly p1,poly p2, const ring r1, const ring r2)
4038{
4039  assume( r1 == r2 || rSamePolyRep(r1, r2) ); // will be used in rEqual!
4040  assume( r1->cf == r2->cf );
4041 
4042  while ((p1 != NULL) && (p2 != NULL))
4043  {
4044    // returns 1 if ExpVector(p)==ExpVector(q): does not compare numbers !!
4045    // #define p_LmEqual(p1, p2, r) p_ExpVectorEqual(p1, p2, r)
4046
4047    if (! p_ExpVectorEqual(p1, p2, r1, r2))
4048      return FALSE;
4049   
4050    if (! n_Equal(p_GetCoeff(p1,r1), p_GetCoeff(p2,r2), r1->cf ))
4051      return FALSE;
4052   
4053    pIter(p1);
4054    pIter(p2);
4055  }
4056  return (p1==p2);
4057}
4058
4059/*2
4060*returns TRUE if p1 is a skalar multiple of p2
4061*assume p1 != NULL and p2 != NULL
4062*/
4063BOOLEAN p_ComparePolys(poly p1,poly p2, const ring r)
4064{
4065  number n,nn;
4066  pAssume(p1 != NULL && p2 != NULL);
4067
4068  if (!p_LmEqual(p1,p2,r)) //compare leading mons
4069      return FALSE;
4070  if ((pNext(p1)==NULL) && (pNext(p2)!=NULL))
4071     return FALSE;
4072  if ((pNext(p2)==NULL) && (pNext(p1)!=NULL))
4073     return FALSE;
4074  if (pLength(p1) != pLength(p2))
4075    return FALSE;
4076#ifdef HAVE_RINGS
4077  if (rField_is_Ring(r))
4078  {
4079    if (!n_DivBy(p_GetCoeff(p1, r), p_GetCoeff(p2, r), r)) return FALSE;
4080  }
4081#endif
4082  n=n_Div(p_GetCoeff(p1,r),p_GetCoeff(p2,r),r);
4083  while ((p1 != NULL) /*&& (p2 != NULL)*/)
4084  {
4085    if ( ! p_LmEqual(p1, p2,r))
4086    {
4087        n_Delete(&n, r);
4088        return FALSE;
4089    }
4090    if (!n_Equal(p_GetCoeff(p1, r), nn = n_Mult(p_GetCoeff(p2, r),n, r->cf), r->cf))
4091    {
4092      n_Delete(&n, r);
4093      n_Delete(&nn, r);
4094      return FALSE;
4095    }
4096    n_Delete(&nn, r);
4097    pIter(p1);
4098    pIter(p2);
4099  }
4100  n_Delete(&n, r);
4101  return TRUE;
4102}
4103
4104/*2
4105* returns the length of a (numbers of monomials)
4106* respect syzComp
4107*/
4108poly p_Last(const poly p, int &l, const ring r)
4109{
4110  if (p == NULL)
4111  {
4112    l = 0;
4113    return NULL;
4114  }
4115  l = 1;
4116  poly a = p;
4117  if (! rIsSyzIndexRing(r))
4118  {
4119    poly next = pNext(a);
4120    while (next!=NULL)
4121    {
4122      a = next;
4123      next = pNext(a);     
4124      l++;
4125    }
4126  }
4127  else
4128  {
4129    int curr_limit = rGetCurrSyzLimit(r);
4130    poly pp = a;
4131    while ((a=pNext(a))!=NULL)
4132    {
4133      if (p_GetComp(a,r)<=curr_limit/*syzComp*/)
4134        l++;
4135      else break;
4136      pp = a;
4137    }
4138    a=pp;
4139  }
4140  return a;
4141}
4142
4143int p_Var(poly m,const ring r)
4144{
4145  if (m==NULL) return 0;
4146  if (pNext(m)!=NULL) return 0;
4147  int i,e=0;
4148  for (i=rVar(r); i>0; i--)
4149  {
4150    int exp=p_GetExp(m,i,r);
4151    if (exp==1)
4152    {
4153      if (e==0) e=i;
4154      else return 0;
4155    }
4156    else if (exp!=0)
4157    {
4158      return 0;
4159    }
4160  }
4161  return e;
4162}
4163
4164/*2
4165*the minimal index of used variables - 1
4166*/
4167int p_LowVar (poly p, const ring r)
4168{
4169  int k,l,lex;
4170
4171  if (p == NULL) return -1;
4172
4173  k = 32000;/*a very large dummy value*/
4174  while (p != NULL)
4175  {
4176    l = 1;
4177    lex = p_GetExp(p,l,r);
4178    while ((l < (rVar(r))) && (lex == 0))
4179    {
4180      l++;
4181      lex = p_GetExp(p,l,r);
4182    }
4183    l--;
4184    if (l < k) k = l;
4185    pIter(p);
4186  }
4187  return k;
4188}
4189
4190/*2
4191* verschiebt die Indizees der Modulerzeugenden um i
4192*/
4193void p_Shift (poly * p,int i, const ring r)
4194{
4195  poly qp1 = *p,qp2 = *p;/*working pointers*/
4196  int     j = p_MaxComp(*p,r),k = p_MinComp(*p,r);
4197
4198  if (j+i < 0) return ;
4199  while (qp1 != NULL)
4200  {
4201    if ((p_GetComp(qp1,r)+i > 0) || ((j == -i) && (j == k)))
4202    {
4203      p_AddComp(qp1,i,r);
4204      p_SetmComp(qp1,r);
4205      qp2 = qp1;
4206      pIter(qp1);
4207    }
4208    else
4209    {
4210      if (qp2 == *p)
4211      {
4212        pIter(*p);
4213        p_LmDelete(&qp2,r);
4214        qp2 = *p;
4215        qp1 = *p;
4216      }
4217      else
4218      {
4219        qp2->next = qp1->next;
4220        if (qp1!=NULL) p_LmDelete(&qp1,r);
4221        qp1 = qp2->next;
4222      }
4223    }
4224  }
4225}
4226
4227/***************************************************************
4228 *
4229 * Storage Managament Routines
4230 *
4231 ***************************************************************/
4232
4233
4234static inline unsigned long GetBitFields(long e,
4235                                         unsigned int s, unsigned int n)
4236{
4237#define Sy_bit_L(x)     (((unsigned long)1L)<<(x))
4238  unsigned int i = 0;
4239  unsigned long  ev = 0L;
4240  assume(n > 0 && s < BIT_SIZEOF_LONG);
4241  do
4242  {
4243    assume(s+i < BIT_SIZEOF_LONG);
4244    if (e > (long) i) ev |= Sy_bit_L(s+i);
4245    else break;
4246    i++;
4247  }
4248  while (i < n);
4249  return ev;
4250}
4251
4252// Short Exponent Vectors are used for fast divisibility tests
4253// ShortExpVectors "squeeze" an exponent vector into one word as follows:
4254// Let n = BIT_SIZEOF_LONG / pVariables.
4255// If n == 0 (i.e. pVariables > BIT_SIZE_OF_LONG), let m == the number
4256// of non-zero exponents. If (m>BIT_SIZEOF_LONG), then sev = ~0, else
4257// first m bits of sev are set to 1.
4258// Otherwise (i.e. pVariables <= BIT_SIZE_OF_LONG)
4259// represented by a bit-field of length n (resp. n+1 for some
4260// exponents). If the value of an exponent is greater or equal to n, then
4261// all of its respective n bits are set to 1. If the value of an exponent
4262// is smaller than n, say m, then only the first m bits of the respective
4263// n bits are set to 1, the others are set to 0.
4264// This way, we have:
4265// exp1 / exp2 ==> (ev1 & ~ev2) == 0, i.e.,
4266// if (ev1 & ~ev2) then exp1 does not divide exp2
4267unsigned long p_GetShortExpVector(poly p, const ring r)
4268{
4269  assume(p != NULL);
4270  if (p == NULL) return 0;
4271  unsigned long ev = 0; // short exponent vector
4272  unsigned int n = BIT_SIZEOF_LONG / r->N; // number of bits per exp
4273  unsigned int m1; // highest bit which is filled with (n+1)
4274  unsigned int i = 0, j=1;
4275
4276  if (n == 0)
4277  {
4278    if (r->N <2*BIT_SIZEOF_LONG)
4279    {
4280      n=1;
4281      m1=0;
4282    }
4283    else
4284    {
4285      for (; j<=(unsigned long) r->N; j++)
4286      {
4287        if (p_GetExp(p,j,r) > 0) i++;
4288        if (i == BIT_SIZEOF_LONG) break;
4289      }
4290      if (i>0)
4291        ev = ~((unsigned long)0) >> ((unsigned long) (BIT_SIZEOF_LONG - i));
4292      return ev;
4293    }
4294  }
4295  else
4296  {
4297    m1 = (n+1)*(BIT_SIZEOF_LONG - n*r->N);
4298  }
4299
4300  n++;
4301  while (i<m1)
4302  {
4303    ev |= GetBitFields(p_GetExp(p, j,r), i, n);
4304    i += n;
4305    j++;
4306  }
4307
4308  n--;
4309  while (i<BIT_SIZEOF_LONG)
4310  {
4311    ev |= GetBitFields(p_GetExp(p, j,r), i, n);
4312    i += n;
4313    j++;
4314  }
4315  return ev;
4316}
4317
4318/***************************************************************
4319 *
4320 * p_ShallowDelete
4321 *
4322 ***************************************************************/
4323#undef LINKAGE
4324#define LINKAGE
4325#undef p_Delete__T
4326#define p_Delete__T p_ShallowDelete
4327#undef n_Delete__T
4328#define n_Delete__T(n, r) do {} while (0)
4329
4330#include <polys/templates/p_Delete__T.cc>
4331
Note: See TracBrowser for help on using the repository browser.