source: git/libpolys/polys/monomials/p_polys.cc @ c462b55

spielwiese
Last change on this file since c462b55 was ba0fc3, checked in by Hans Schoenemann <hannes@…>, 13 years ago
p_MinDeg, p_DegW -> p_polys.cc
  • Property mode set to 100644
File size: 71.5 KB
Line 
1/****************************************
2*  Computer Algebra System SINGULAR     *
3****************************************/
4/***************************************************************
5 *  File:    p_polys.cc
6 *  Purpose: implementation of currRing independent poly procedures
7 *  Author:  obachman (Olaf Bachmann)
8 *  Created: 8/00
9 *  Version: $Id$
10 *******************************************************************/
11
12#include <ctype.h>
13
14#include <misc/auxiliary.h>
15
16#include <polys/monomials/ring.h>
17#include <polys/monomials/p_polys.h>
18#include <polys/monomials/ring.h>
19#include <polys/weight.h>
20#include <coeffs/longrat.h>
21#include <misc/options.h>
22#include <misc/intvec.h>
23// #include <???/ideals.h>
24// #include <???/int64vec.h>
25#ifndef NDEBUG
26// #include <???/febase.h>
27#endif
28
29/***************************************************************
30 *
31 * Completing what needs to be set for the monomial
32 *
33 ***************************************************************/
34// this is special for the syz stuff
35static int* _components = NULL;
36static long* _componentsShifted = NULL;
37static int _componentsExternal = 0;
38
39BOOLEAN pSetm_error=0;
40
41#ifndef NDEBUG
42# define MYTEST 0
43#else /* ifndef NDEBUG */
44# define MYTEST 0
45#endif /* ifndef NDEBUG */
46
47void p_Setm_General(poly p, const ring r)
48{
49  p_LmCheckPolyRing(p, r);
50  int pos=0;
51  if (r->typ!=NULL)
52  {
53    loop
54    {
55      long ord=0;
56      sro_ord* o=&(r->typ[pos]);
57      switch(o->ord_typ)
58      {
59        case ro_dp:
60        {
61          int a,e;
62          a=o->data.dp.start;
63          e=o->data.dp.end;
64          for(int i=a;i<=e;i++) ord+=p_GetExp(p,i,r);
65          p->exp[o->data.dp.place]=ord;
66          break;
67        }
68        case ro_wp_neg:
69          ord=POLY_NEGWEIGHT_OFFSET;
70          // no break;
71        case ro_wp:
72        {
73          int a,e;
74          a=o->data.wp.start;
75          e=o->data.wp.end;
76          int *w=o->data.wp.weights;
77#if 1
78          for(int i=a;i<=e;i++) ord+=p_GetExp(p,i,r)*w[i-a];
79#else
80          long ai;
81          int ei,wi;
82          for(int i=a;i<=e;i++)
83          {
84             ei=p_GetExp(p,i,r);
85             wi=w[i-a];
86             ai=ei*wi;
87             if (ai/ei!=wi) pSetm_error=TRUE;
88             ord+=ai;
89             if (ord<ai) pSetm_error=TRUE;
90          }
91#endif
92          p->exp[o->data.wp.place]=ord;
93          break;
94        }
95      case ro_wp64:
96        {
97          int64 ord=0;
98          int a,e;
99          a=o->data.wp64.start;
100          e=o->data.wp64.end;
101          int64 *w=o->data.wp64.weights64;
102          int64 ei,wi,ai;
103          for(int i=a;i<=e;i++)
104          {
105            //Print("exp %d w %d \n",p_GetExp(p,i,r),(int)w[i-a]);
106            //ord+=((int64)p_GetExp(p,i,r))*w[i-a];
107            ei=(int64)p_GetExp(p,i,r);
108            wi=w[i-a];
109            ai=ei*wi;
110            if(ei!=0 && ai/ei!=wi)
111            {
112              pSetm_error=TRUE;
113              #if SIZEOF_LONG == 4
114              Print("ai %lld, wi %lld\n",ai,wi);
115              #else
116              Print("ai %ld, wi %ld\n",ai,wi);
117              #endif
118            }
119            ord+=ai;
120            if (ord<ai)
121            {
122              pSetm_error=TRUE;
123              #if SIZEOF_LONG == 4
124              Print("ai %lld, ord %lld\n",ai,ord);
125              #else
126              Print("ai %ld, ord %ld\n",ai,ord);
127              #endif
128            }
129          }
130          int64 mask=(int64)0x7fffffff;
131          long a_0=(long)(ord&mask); //2^31
132          long a_1=(long)(ord >>31 ); /*(ord/(mask+1));*/
133
134          //Print("mask: %x,  ord: %d,  a_0: %d,  a_1: %d\n"
135          //,(int)mask,(int)ord,(int)a_0,(int)a_1);
136                    //Print("mask: %d",mask);
137
138          p->exp[o->data.wp64.place]=a_1;
139          p->exp[o->data.wp64.place+1]=a_0;
140//            if(p_Setm_error) Print("***************************\n
141//                                    ***************************\n
142//                                    **WARNING: overflow error**\n
143//                                    ***************************\n
144//                                    ***************************\n");
145          break;
146        }
147        case ro_cp:
148        {
149          int a,e;
150          a=o->data.cp.start;
151          e=o->data.cp.end;
152          int pl=o->data.cp.place;
153          for(int i=a;i<=e;i++) { p->exp[pl]=p_GetExp(p,i,r); pl++; }
154          break;
155        }
156        case ro_syzcomp:
157        {
158          int c=p_GetComp(p,r);
159          long sc = c;
160          int* Components = (_componentsExternal ? _components :
161                             o->data.syzcomp.Components);
162          long* ShiftedComponents = (_componentsExternal ? _componentsShifted:
163                                     o->data.syzcomp.ShiftedComponents);
164          if (ShiftedComponents != NULL)
165          {
166            assume(Components != NULL);
167            assume(c == 0 || Components[c] != 0);
168            sc = ShiftedComponents[Components[c]];
169            assume(c == 0 || sc != 0);
170          }
171          p->exp[o->data.syzcomp.place]=sc;
172          break;
173        }
174        case ro_syz:
175        {
176          const unsigned long c = p_GetComp(p, r);
177          const short place = o->data.syz.place;
178          const int limit = o->data.syz.limit;
179         
180          if (c > limit)
181            p->exp[place] = o->data.syz.curr_index;
182          else if (c > 0)
183          {
184            assume( (1 <= c) && (c <= limit) );
185            p->exp[place]= o->data.syz.syz_index[c];
186          }
187          else
188          {
189            assume(c == 0);
190            p->exp[place]= 0;
191          }
192          break;
193        }
194        // Prefix for Induced Schreyer ordering
195        case ro_isTemp: // Do nothing?? (to be removed into suffix later on...?)
196        {
197          assume(p != NULL);
198
199#ifndef NDEBUG
200#if MYTEST
201          Print("p_Setm_General: isTemp ord: pos: %d, p: ", pos);  p_DebugPrint(p, r, r, 1);
202#endif
203#endif
204          int c = p_GetComp(p, r);
205
206          assume( c >= 0 );
207
208          // Let's simulate case ro_syz above....
209          // Should accumulate (by Suffix) and be a level indicator
210          const int* const pVarOffset = o->data.isTemp.pVarOffset;
211
212          assume( pVarOffset != NULL );
213
214          // TODO: Can this be done in the suffix???
215          for( int i = 1; i <= r->N; i++ ) // No v[0] here!!!
216          {
217            const int vo = pVarOffset[i];
218            if( vo != -1) // TODO: optimize: can be done once!
219            {
220              // Hans! Please don't break it again! p_SetExp(p, ..., r, vo) is correct:
221              p_SetExp(p, p_GetExp(p, i, r), r, vo); // copy put them verbatim
222              // Hans! Please don't break it again! p_GetExp(p, r, vo) is correct:
223              assume( p_GetExp(p, r, vo) == p_GetExp(p, i, r) ); // copy put them verbatim
224            }
225          }
226#ifndef NDEBUG
227          for( int i = 1; i <= r->N; i++ ) // No v[0] here!!!
228          {
229            const int vo = pVarOffset[i];
230            if( vo != -1) // TODO: optimize: can be done once!
231            {
232              // Hans! Please don't break it again! p_GetExp(p, r, vo) is correct:
233              assume( p_GetExp(p, r, vo) == p_GetExp(p, i, r) ); // copy put them verbatim
234            }
235          }
236#if MYTEST
237//          if( p->exp[o->data.isTemp.start] > 0 )
238//          {
239//            PrintS("Initial Value: "); p_DebugPrint(p, r, r, 1);
240//          }
241#endif
242#endif
243          break;
244        }
245
246        // Suffix for Induced Schreyer ordering
247        case ro_is:
248        {
249#ifndef NDEBUG
250#if MYTEST
251          Print("p_Setm_General: ro_is ord: pos: %d, p: ", pos);  p_DebugPrint(p, r, r, 1);
252#endif
253#endif
254
255          assume(p != NULL);
256
257          int c = p_GetComp(p, r);
258
259          assume( c >= 0 );
260          const ideal F = o->data.is.F;
261          const int limit = o->data.is.limit;
262
263          if( F != NULL && c > limit )
264          {
265#ifndef NDEBUG
266#if MYTEST
267            Print("p_Setm_General: ro_is : in rSetm: pos: %d, c: %d >  limit: %d\n", c, pos, limit); // p_DebugPrint(p, r, r, 1);
268#endif
269#endif
270
271            c -= limit;
272            assume( c > 0 );
273            c--;
274
275            assume( c < IDELEMS(F) ); // What about others???
276
277            const poly pp = F->m[c]; // get reference monomial!!!
278
279#ifndef NDEBUG
280#if MYTEST
281            Print("Respective F[c - %d: %d] pp: ", limit, c); 
282            p_DebugPrint(pp, r, r, 1);
283#endif
284#endif
285
286
287            assume(pp != NULL);
288            if(pp == NULL) break;
289
290            const int start = o->data.is.start;
291            const int end = o->data.is.end;
292
293            assume(start <= end);
294             
295//          const int limit = o->data.is.limit;
296          assume( limit >= 0 );
297
298//        const int st = o->data.isTemp.start;       
299
300          if( c > limit )
301            p->exp[start] = 1;
302//          else
303//            p->exp[start] = 0;
304
305             
306#ifndef NDEBUG
307            Print("p_Setm_General: is(-Temp-) :: c: %d, limit: %d, [st:%d] ===>>> %ld\n", c, limit, start, p->exp[start]);
308#endif       
309   
310
311            for( int i = start; i <= end; i++) // v[0] may be here...
312              p->exp[i] += pp->exp[i]; // !!!!!!!! ADD corresponding LT(F)
313
314       
315
316             
317#ifndef NDEBUG
318            const int* const pVarOffset = o->data.is.pVarOffset;
319
320            assume( pVarOffset != NULL );
321
322            for( int i = 1; i <= r->N; i++ ) // No v[0] here!!!
323            {
324              const int vo = pVarOffset[i];
325              if( vo != -1) // TODO: optimize: can be done once!
326                // Hans! Please don't break it again! p_GetExp(p/pp, r, vo) is correct:
327                assume( p_GetExp(p, r, vo) == (p_GetExp(p, i, r) + p_GetExp(pp, r, vo)) );
328            }
329            // TODO: how to check this for computed values???
330#endif
331          } else
332          {
333            const int* const pVarOffset = o->data.is.pVarOffset;
334
335            // What about v[0] - component: it will be added later by
336            // suffix!!!
337            // TODO: Test it!
338            const int vo = pVarOffset[0];
339            if( vo != -1 )
340              p->exp[vo] = c; // initial component v[0]!
341
342#ifndef NDEBUG
343#if MYTEST
344            Print("p_Setm_General: ro_is :: c: %d <= limit: %d, vo: %d, exp: %d\n", c, limit, vo, p->exp[vo]);
345            p_DebugPrint(p, r, r, 1);
346#endif       
347#endif       
348          }
349           
350
351          break;
352        }
353        default:
354          dReportError("wrong ord in rSetm:%d\n",o->ord_typ);
355          return;
356      }
357      pos++;
358      if (pos == r->OrdSize) return;
359    }
360  }
361}
362
363void p_Setm_Syz(poly p, ring r, int* Components, long* ShiftedComponents)
364{
365  _components = Components;
366  _componentsShifted = ShiftedComponents;
367  _componentsExternal = 1;
368  p_Setm_General(p, r);
369  _componentsExternal = 0;
370}
371
372// dummy for lp, ls, etc
373void p_Setm_Dummy(poly p, const ring r)
374{
375  p_LmCheckPolyRing(p, r);
376}
377
378// for dp, Dp, ds, etc
379void p_Setm_TotalDegree(poly p, const ring r)
380{
381  p_LmCheckPolyRing(p, r);
382  p->exp[r->pOrdIndex] = p_Totaldegree(p, r);
383}
384
385// for wp, Wp, ws, etc
386void p_Setm_WFirstTotalDegree(poly p, const ring r)
387{
388  p_LmCheckPolyRing(p, r);
389  p->exp[r->pOrdIndex] = p_WFirstTotalDegree(p, r);
390}
391
392p_SetmProc p_GetSetmProc(ring r)
393{
394  // covers lp, rp, ls,
395  if (r->typ == NULL) return p_Setm_Dummy;
396
397  if (r->OrdSize == 1)
398  {
399    if (r->typ[0].ord_typ == ro_dp &&
400        r->typ[0].data.dp.start == 1 &&
401        r->typ[0].data.dp.end == r->N &&
402        r->typ[0].data.dp.place == r->pOrdIndex)
403      return p_Setm_TotalDegree;
404    if (r->typ[0].ord_typ == ro_wp &&
405        r->typ[0].data.wp.start == 1 &&
406        r->typ[0].data.wp.end == r->N &&
407        r->typ[0].data.wp.place == r->pOrdIndex &&
408        r->typ[0].data.wp.weights == r->firstwv)
409      return p_Setm_WFirstTotalDegree;
410  }
411  return p_Setm_General;
412}
413
414
415/* -------------------------------------------------------------------*/
416/* several possibilities for pFDeg: the degree of the head term       */
417
418/* comptible with ordering */
419long p_Deg(poly a, const ring r)
420{
421  p_LmCheckPolyRing(a, r);
422  assume(p_GetOrder(a, r) == p_WTotaldegree(a, r));
423  return p_GetOrder(a, r);
424}
425
426// p_WTotalDegree for weighted orderings
427// whose first block covers all variables
428long p_WFirstTotalDegree(poly p, const ring r)
429{
430  int i;
431  long sum = 0;
432
433  for (i=1; i<= r->firstBlockEnds; i++)
434  {
435    sum += p_GetExp(p, i, r)*r->firstwv[i-1];
436  }
437  return sum;
438}
439
440/*2
441* compute the degree of the leading monomial of p
442* with respect to weigths from the ordering
443* the ordering is not compatible with degree so do not use p->Order
444*/
445long p_WTotaldegree(poly p, const ring r)
446{
447  p_LmCheckPolyRing(p, r);
448  int i, k;
449  long j =0;
450
451  // iterate through each block:
452  for (i=0;r->order[i]!=0;i++)
453  {
454    int b0=r->block0[i];
455    int b1=r->block1[i];
456    switch(r->order[i])
457    {
458      case ringorder_M:
459        for (k=b0 /*r->block0[i]*/;k<=b1 /*r->block1[i]*/;k++)
460        { // in jedem block:
461          j+= p_GetExp(p,k,r)*r->wvhdl[i][k - b0 /*r->block0[i]*/]*r->OrdSgn;
462        }
463        break;
464      case ringorder_wp:
465      case ringorder_ws:
466      case ringorder_Wp:
467      case ringorder_Ws:
468        for (k=b0 /*r->block0[i]*/;k<=b1 /*r->block1[i]*/;k++)
469        { // in jedem block:
470          j+= p_GetExp(p,k,r)*r->wvhdl[i][k - b0 /*r->block0[i]*/];
471        }
472        break;
473      case ringorder_lp:
474      case ringorder_ls:
475      case ringorder_rs:
476      case ringorder_dp:
477      case ringorder_ds:
478      case ringorder_Dp:
479      case ringorder_Ds:
480      case ringorder_rp:
481        for (k=b0 /*r->block0[i]*/;k<=b1 /*r->block1[i]*/;k++)
482        {
483          j+= p_GetExp(p,k,r);
484        }
485        break;
486      case ringorder_a64:
487        {
488          int64* w=(int64*)r->wvhdl[i];
489          for (k=0;k<=(b1 /*r->block1[i]*/ - b0 /*r->block0[i]*/);k++)
490          {
491            //there should be added a line which checks if w[k]>2^31
492            j+= p_GetExp(p,k+1, r)*(long)w[k];
493          }
494          //break;
495          return j;
496        }
497      case ringorder_c:
498      case ringorder_C:
499      case ringorder_S:
500      case ringorder_s:
501      case ringorder_IS:
502      case ringorder_aa:
503        break;
504      case ringorder_a:
505        for (k=b0 /*r->block0[i]*/;k<=b1 /*r->block1[i]*/;k++)
506        { // only one line
507          j+= p_GetExp(p,k, r)*r->wvhdl[i][ k- b0 /*r->block0[i]*/];
508        }
509        //break;
510        return j;
511
512#ifndef NDEBUG
513      default:
514        Print("missing order %d in p_WTotaldegree\n",r->order[i]);
515        break;
516#endif
517    }
518  }
519  return  j;
520}
521
522long p_DegW(poly p, const short *w, const ring R)
523{
524  long r=~0L;
525
526  while (p!=NULL)
527  {
528    long t=totaldegreeWecart_IV(p,R,w);
529    if (t>r) r=t;
530    pIter(p);
531  }
532  return r;
533}
534
535int p_Weight(int i, const ring r)
536{
537  if ((r->firstwv==NULL) || (i>r->firstBlockEnds))
538  {
539    return 1;
540  }
541  return r->firstwv[i-1];
542}
543
544long p_WDegree(poly p, const ring r)
545{
546  if (r->firstwv==NULL) return p_Totaldegree(p, r);
547  p_LmCheckPolyRing(p, r);
548  int i;
549  long j =0;
550
551  for(i=1;i<=r->firstBlockEnds;i++)
552    j+=p_GetExp(p, i, r)*r->firstwv[i-1];
553
554  for (;i<=r->N;i++)
555    j+=p_GetExp(p,i, r)*p_Weight(i, r);
556
557  return j;
558}
559
560
561/* ---------------------------------------------------------------------*/
562/* several possibilities for pLDeg: the maximal degree of a monomial in p*/
563/*  compute in l also the pLength of p                                   */
564
565/*2
566* compute the length of a polynomial (in l)
567* and the degree of the monomial with maximal degree: the last one
568*/
569long pLDeg0(poly p,int *l, const ring r)
570{
571  p_CheckPolyRing(p, r);
572  long k= p_GetComp(p, r);
573  int ll=1;
574
575  if (k > 0)
576  {
577    while ((pNext(p)!=NULL) && (p_GetComp(pNext(p), r)==k))
578    {
579      pIter(p);
580      ll++;
581    }
582  }
583  else
584  {
585     while (pNext(p)!=NULL)
586     {
587       pIter(p);
588       ll++;
589     }
590  }
591  *l=ll;
592  return r->pFDeg(p, r);
593}
594
595/*2
596* compute the length of a polynomial (in l)
597* and the degree of the monomial with maximal degree: the last one
598* but search in all components before syzcomp
599*/
600long pLDeg0c(poly p,int *l, const ring r)
601{
602  assume(p!=NULL);
603#ifdef PDEBUG
604  _p_Test(p,r,PDEBUG);
605#endif
606  p_CheckPolyRing(p, r);
607  long o;
608  int ll=1;
609
610  if (! rIsSyzIndexRing(r))
611  {
612    while (pNext(p) != NULL)
613    {
614      pIter(p);
615      ll++;
616    }
617    o = r->pFDeg(p, r);
618  }
619  else
620  {
621    int curr_limit = rGetCurrSyzLimit(r);
622    poly pp = p;
623    while ((p=pNext(p))!=NULL)
624    {
625      if (p_GetComp(p, r)<=curr_limit/*syzComp*/)
626        ll++;
627      else break;
628      pp = p;
629    }
630#ifdef PDEBUG
631    _p_Test(pp,r,PDEBUG);
632#endif
633    o = r->pFDeg(pp, r);
634  }
635  *l=ll;
636  return o;
637}
638
639/*2
640* compute the length of a polynomial (in l)
641* and the degree of the monomial with maximal degree: the first one
642* this works for the polynomial case with degree orderings
643* (both c,dp and dp,c)
644*/
645long pLDegb(poly p,int *l, const ring r)
646{
647  p_CheckPolyRing(p, r);
648  long k= p_GetComp(p, r);
649  long o = r->pFDeg(p, r);
650  int ll=1;
651
652  if (k != 0)
653  {
654    while (((p=pNext(p))!=NULL) && (p_GetComp(p, r)==k))
655    {
656      ll++;
657    }
658  }
659  else
660  {
661    while ((p=pNext(p)) !=NULL)
662    {
663      ll++;
664    }
665  }
666  *l=ll;
667  return o;
668}
669
670/*2
671* compute the length of a polynomial (in l)
672* and the degree of the monomial with maximal degree:
673* this is NOT the last one, we have to look for it
674*/
675long pLDeg1(poly p,int *l, const ring r)
676{
677  p_CheckPolyRing(p, r);
678  long k= p_GetComp(p, r);
679  int ll=1;
680  long  t,max;
681
682  max=r->pFDeg(p, r);
683  if (k > 0)
684  {
685    while (((p=pNext(p))!=NULL) && (p_GetComp(p, r)==k))
686    {
687      t=r->pFDeg(p, r);
688      if (t>max) max=t;
689      ll++;
690    }
691  }
692  else
693  {
694    while ((p=pNext(p))!=NULL)
695    {
696      t=r->pFDeg(p, r);
697      if (t>max) max=t;
698      ll++;
699    }
700  }
701  *l=ll;
702  return max;
703}
704
705/*2
706* compute the length of a polynomial (in l)
707* and the degree of the monomial with maximal degree:
708* this is NOT the last one, we have to look for it
709* in all components
710*/
711long pLDeg1c(poly p,int *l, const ring r)
712{
713  p_CheckPolyRing(p, r);
714  int ll=1;
715  long  t,max;
716
717  max=r->pFDeg(p, r);
718  if (rIsSyzIndexRing(r))
719  {
720    long limit = rGetCurrSyzLimit(r);
721    while ((p=pNext(p))!=NULL)
722    {
723      if (p_GetComp(p, r)<=limit)
724      {
725        if ((t=r->pFDeg(p, r))>max) max=t;
726        ll++;
727      }
728      else break;
729    }
730  }
731  else
732  {
733    while ((p=pNext(p))!=NULL)
734    {
735      if ((t=r->pFDeg(p, r))>max) max=t;
736      ll++;
737    }
738  }
739  *l=ll;
740  return max;
741}
742
743// like pLDeg1, only pFDeg == pDeg
744long pLDeg1_Deg(poly p,int *l, const ring r)
745{
746  assume(r->pFDeg == pDeg);
747  p_CheckPolyRing(p, r);
748  long k= p_GetComp(p, r);
749  int ll=1;
750  long  t,max;
751
752  max=p_GetOrder(p, r);
753  if (k > 0)
754  {
755    while (((p=pNext(p))!=NULL) && (p_GetComp(p, r)==k))
756    {
757      t=p_GetOrder(p, r);
758      if (t>max) max=t;
759      ll++;
760    }
761  }
762  else
763  {
764    while ((p=pNext(p))!=NULL)
765    {
766      t=p_GetOrder(p, r);
767      if (t>max) max=t;
768      ll++;
769    }
770  }
771  *l=ll;
772  return max;
773}
774
775long pLDeg1c_Deg(poly p,int *l, const ring r)
776{
777  assume(r->pFDeg == pDeg);
778  p_CheckPolyRing(p, r);
779  int ll=1;
780  long  t,max;
781
782  max=p_GetOrder(p, r);
783  if (rIsSyzIndexRing(r))
784  {
785    long limit = rGetCurrSyzLimit(r);
786    while ((p=pNext(p))!=NULL)
787    {
788      if (p_GetComp(p, r)<=limit)
789      {
790        if ((t=p_GetOrder(p, r))>max) max=t;
791        ll++;
792      }
793      else break;
794    }
795  }
796  else
797  {
798    while ((p=pNext(p))!=NULL)
799    {
800      if ((t=p_GetOrder(p, r))>max) max=t;
801      ll++;
802    }
803  }
804  *l=ll;
805  return max;
806}
807
808// like pLDeg1, only pFDeg == pTotoalDegree
809long pLDeg1_Totaldegree(poly p,int *l, const ring r)
810{
811  p_CheckPolyRing(p, r);
812  long k= p_GetComp(p, r);
813  int ll=1;
814  long  t,max;
815
816  max=p_Totaldegree(p, r);
817  if (k > 0)
818  {
819    while (((p=pNext(p))!=NULL) && (p_GetComp(p, r)==k))
820    {
821      t=p_Totaldegree(p, r);
822      if (t>max) max=t;
823      ll++;
824    }
825  }
826  else
827  {
828    while ((p=pNext(p))!=NULL)
829    {
830      t=p_Totaldegree(p, r);
831      if (t>max) max=t;
832      ll++;
833    }
834  }
835  *l=ll;
836  return max;
837}
838
839long pLDeg1c_Totaldegree(poly p,int *l, const ring r)
840{
841  p_CheckPolyRing(p, r);
842  int ll=1;
843  long  t,max;
844
845  max=p_Totaldegree(p, r);
846  if (rIsSyzIndexRing(r))
847  {
848    long limit = rGetCurrSyzLimit(r);
849    while ((p=pNext(p))!=NULL)
850    {
851      if (p_GetComp(p, r)<=limit)
852      {
853        if ((t=p_Totaldegree(p, r))>max) max=t;
854        ll++;
855      }
856      else break;
857    }
858  }
859  else
860  {
861    while ((p=pNext(p))!=NULL)
862    {
863      if ((t=p_Totaldegree(p, r))>max) max=t;
864      ll++;
865    }
866  }
867  *l=ll;
868  return max;
869}
870
871// like pLDeg1, only pFDeg == p_WFirstTotalDegree
872long pLDeg1_WFirstTotalDegree(poly p,int *l, const ring r)
873{
874  p_CheckPolyRing(p, r);
875  long k= p_GetComp(p, r);
876  int ll=1;
877  long  t,max;
878
879  max=p_WFirstTotalDegree(p, r);
880  if (k > 0)
881  {
882    while (((p=pNext(p))!=NULL) && (p_GetComp(p, r)==k))
883    {
884      t=p_WFirstTotalDegree(p, r);
885      if (t>max) max=t;
886      ll++;
887    }
888  }
889  else
890  {
891    while ((p=pNext(p))!=NULL)
892    {
893      t=p_WFirstTotalDegree(p, r);
894      if (t>max) max=t;
895      ll++;
896    }
897  }
898  *l=ll;
899  return max;
900}
901
902long pLDeg1c_WFirstTotalDegree(poly p,int *l, const ring r)
903{
904  p_CheckPolyRing(p, r);
905  int ll=1;
906  long  t,max;
907
908  max=p_WFirstTotalDegree(p, r);
909  if (rIsSyzIndexRing(r))
910  {
911    long limit = rGetCurrSyzLimit(r);
912    while ((p=pNext(p))!=NULL)
913    {
914      if (p_GetComp(p, r)<=limit)
915      {
916        if ((t=p_Totaldegree(p, r))>max) max=t;
917        ll++;
918      }
919      else break;
920    }
921  }
922  else
923  {
924    while ((p=pNext(p))!=NULL)
925    {
926      if ((t=p_Totaldegree(p, r))>max) max=t;
927      ll++;
928    }
929  }
930  *l=ll;
931  return max;
932}
933
934/***************************************************************
935 *
936 * Maximal Exponent business
937 *
938 ***************************************************************/
939
940static inline unsigned long
941p_GetMaxExpL2(unsigned long l1, unsigned long l2, const ring r,
942              unsigned long number_of_exp)
943{
944  const unsigned long bitmask = r->bitmask;
945  unsigned long ml1 = l1 & bitmask;
946  unsigned long ml2 = l2 & bitmask;
947  unsigned long max = (ml1 > ml2 ? ml1 : ml2);
948  unsigned long j = number_of_exp - 1;
949
950  if (j > 0)
951  {
952    unsigned long mask = bitmask << r->BitsPerExp;
953    while (1)
954    {
955      ml1 = l1 & mask;
956      ml2 = l2 & mask;
957      max |= ((ml1 > ml2 ? ml1 : ml2) & mask);
958      j--;
959      if (j == 0) break;
960      mask = mask << r->BitsPerExp;
961    }
962  }
963  return max;
964}
965
966static inline unsigned long
967p_GetMaxExpL2(unsigned long l1, unsigned long l2, const ring r)
968{
969  return p_GetMaxExpL2(l1, l2, r, r->ExpPerLong);
970}
971
972poly p_GetMaxExpP(poly p, const ring r)
973{
974  p_CheckPolyRing(p, r);
975  if (p == NULL) return p_Init(r);
976  poly max = p_LmInit(p, r);
977  pIter(p);
978  if (p == NULL) return max;
979  int i, offset;
980  unsigned long l_p, l_max;
981  unsigned long divmask = r->divmask;
982
983  do
984  {
985    offset = r->VarL_Offset[0];
986    l_p = p->exp[offset];
987    l_max = max->exp[offset];
988    // do the divisibility trick to find out whether l has an exponent
989    if (l_p > l_max ||
990        (((l_max & divmask) ^ (l_p & divmask)) != ((l_max-l_p) & divmask)))
991      max->exp[offset] = p_GetMaxExpL2(l_max, l_p, r);
992
993    for (i=1; i<r->VarL_Size; i++)
994    {
995      offset = r->VarL_Offset[i];
996      l_p = p->exp[offset];
997      l_max = max->exp[offset];
998      // do the divisibility trick to find out whether l has an exponent
999      if (l_p > l_max ||
1000          (((l_max & divmask) ^ (l_p & divmask)) != ((l_max-l_p) & divmask)))
1001        max->exp[offset] = p_GetMaxExpL2(l_max, l_p, r);
1002    }
1003    pIter(p);
1004  }
1005  while (p != NULL);
1006  return max;
1007}
1008
1009unsigned long p_GetMaxExpL(poly p, const ring r, unsigned long l_max)
1010{
1011  unsigned long l_p, divmask = r->divmask;
1012  int i;
1013
1014  while (p != NULL)
1015  {
1016    l_p = p->exp[r->VarL_Offset[0]];
1017    if (l_p > l_max ||
1018        (((l_max & divmask) ^ (l_p & divmask)) != ((l_max-l_p) & divmask)))
1019      l_max = p_GetMaxExpL2(l_max, l_p, r);
1020    for (i=1; i<r->VarL_Size; i++)
1021    {
1022      l_p = p->exp[r->VarL_Offset[i]];
1023      // do the divisibility trick to find out whether l has an exponent
1024      if (l_p > l_max ||
1025          (((l_max & divmask) ^ (l_p & divmask)) != ((l_max-l_p) & divmask)))
1026        l_max = p_GetMaxExpL2(l_max, l_p, r);
1027    }
1028    pIter(p);
1029  }
1030  return l_max;
1031}
1032
1033
1034
1035
1036/***************************************************************
1037 *
1038 * Misc things
1039 *
1040 ***************************************************************/
1041// returns TRUE, if all monoms have the same component
1042BOOLEAN p_OneComp(poly p, const ring r)
1043{
1044  if(p!=NULL)
1045  {
1046    long i = p_GetComp(p, r);
1047    while (pNext(p)!=NULL)
1048    {
1049      pIter(p);
1050      if(i != p_GetComp(p, r)) return FALSE;
1051    }
1052  }
1053  return TRUE;
1054}
1055
1056/*2
1057*test if a monomial /head term is a pure power
1058*/
1059int p_IsPurePower(const poly p, const ring r)
1060{
1061  int i,k=0;
1062
1063  for (i=r->N;i;i--)
1064  {
1065    if (p_GetExp(p,i, r)!=0)
1066    {
1067      if(k!=0) return 0;
1068      k=i;
1069    }
1070  }
1071  return k;
1072}
1073
1074/*2
1075*test if a polynomial is univariate
1076* return -1 for constant,
1077* 0 for not univariate,s
1078* i if dep. on var(i)
1079*/
1080int p_IsUnivariate(poly p, const ring r)
1081{
1082  int i,k=-1;
1083
1084  while (p!=NULL)
1085  {
1086    for (i=r->N;i;i--)
1087    {
1088      if (p_GetExp(p,i, r)!=0)
1089      {
1090        if((k!=-1)&&(k!=i)) return 0;
1091        k=i;
1092      }
1093    }
1094    pIter(p);
1095  }
1096  return k;
1097}
1098
1099// set entry e[i] to 1 if var(i) occurs in p, ignore var(j) if e[j]>0
1100int  p_GetVariables(poly p, int * e, const ring r)
1101{
1102  int i;
1103  int n=0;
1104  while(p!=NULL)
1105  {
1106    n=0;
1107    for(i=r->N; i>0; i--)
1108    {
1109      if(e[i]==0)
1110      {
1111        if (p_GetExp(p,i,r)>0)
1112        {
1113          e[i]=1;
1114          n++;
1115        }
1116      }
1117      else
1118        n++;
1119    }
1120    if (n==r->N) break;
1121    pIter(p);
1122  }
1123  return n;
1124}
1125
1126
1127/*2
1128* returns a polynomial representing the integer i
1129*/
1130poly p_ISet(int i, const ring r)
1131{
1132  poly rc = NULL;
1133  if (i!=0)
1134  {
1135    rc = p_Init(r);
1136    pSetCoeff0(rc,n_Init(i,r->cf));
1137    if (n_IsZero(pGetCoeff(rc),r->cf))
1138      p_LmDelete(&rc,r);
1139  }
1140  return rc;
1141}
1142
1143/*2
1144* an optimized version of p_ISet for the special case 1
1145*/
1146poly p_One(const ring r)
1147{
1148  poly rc = p_Init(r);
1149  pSetCoeff0(rc,n_Init(1,r->cf));
1150  return rc;
1151}
1152
1153void p_Split(poly p, poly *h)
1154{
1155  *h=pNext(p);
1156  pNext(p)=NULL;
1157}
1158
1159/*2
1160* pair has no common factor ? or is no polynomial
1161*/
1162BOOLEAN p_HasNotCF(poly p1, poly p2, const ring r)
1163{
1164
1165  if (p_GetComp(p1,r) > 0 || p_GetComp(p2,r) > 0)
1166    return FALSE;
1167  int i = rVar(r);
1168  loop
1169  {
1170    if ((p_GetExp(p1, i, r) > 0) && (p_GetExp(p2, i, r) > 0))
1171      return FALSE;
1172    i--;
1173    if (i == 0)
1174      return TRUE;
1175  }
1176}
1177
1178/*2
1179* convert monomial given as string to poly, e.g. 1x3y5z
1180*/
1181const char * p_Read(const char *st, poly &rc, const ring r)
1182{
1183  if (r==NULL) { rc=NULL;return st;}
1184  int i,j;
1185  rc = p_Init(r);
1186  const char *s = r->cf->cfRead(st,&(rc->coef),r->cf);
1187  if (s==st)
1188  /* i.e. it does not start with a coeff: test if it is a ringvar*/
1189  {
1190    j = r_IsRingVar(s,r);
1191    if (j >= 0)
1192    {
1193      p_IncrExp(rc,1+j,r);
1194      while (*s!='\0') s++;
1195      goto done;
1196    }
1197  }
1198  while (*s!='\0')
1199  {
1200    char ss[2];
1201    ss[0] = *s++;
1202    ss[1] = '\0';
1203    j = r_IsRingVar(ss,r);
1204    if (j >= 0)
1205    {
1206      const char *s_save=s;
1207      s = eati(s,&i);
1208      if (((unsigned long)i) >  r->bitmask)
1209      {
1210        // exponent to large: it is not a monomial
1211        p_LmDelete(&rc,r);
1212        return s_save;
1213      }
1214      p_AddExp(rc,1+j, (long)i, r);
1215    }
1216    else
1217    {
1218      // 1st char of is not a varname
1219      p_LmDelete(&rc,r);
1220      s--;
1221      return s;
1222    }
1223  }
1224done:
1225  if (n_IsZero(pGetCoeff(rc),r->cf)) p_LmDelete(&rc,r);
1226  else
1227  {
1228#ifdef HAVE_PLURAL
1229    // in super-commutative ring
1230    // squares of anti-commutative variables are zeroes!
1231    if(rIsSCA(r))
1232    {
1233      const unsigned int iFirstAltVar = scaFirstAltVar(r);
1234      const unsigned int iLastAltVar  = scaLastAltVar(r);
1235
1236      assume(rc != NULL);
1237
1238      for(unsigned int k = iFirstAltVar; k <= iLastAltVar; k++)
1239        if( p_GetExp(rc, k, r) > 1 )
1240        {
1241          p_LmDelete(&rc, r);
1242          goto finish;
1243        }
1244    }
1245#endif
1246
1247    p_Setm(rc,r);
1248  }
1249finish:
1250  return s;
1251}
1252poly p_mInit(const char *st, BOOLEAN &ok, const ring r)
1253{
1254  poly p;
1255  const char *s=p_Read(st,p,r);
1256  if (*s!='\0')
1257  {
1258    if ((s!=st)&&isdigit(st[0]))
1259    {
1260      errorreported=TRUE;
1261    }
1262    ok=FALSE;
1263    p_Delete(&p,r);
1264    return NULL;
1265  }
1266  #ifdef PDEBUG
1267  _p_Test(p,r,PDEBUG);
1268  #endif
1269  ok=!errorreported;
1270  return p;
1271}
1272
1273/*2
1274* returns a polynomial representing the number n
1275* destroys n
1276*/
1277poly p_NSet(number n, const ring r)
1278{
1279  if (n_IsZero(n,r->cf))
1280  {
1281    n_Delete(&n, r->cf);
1282    return NULL;
1283  }
1284  else
1285  {
1286    poly rc = p_Init(r);
1287    pSetCoeff0(rc,n);
1288    return rc;
1289  }
1290}
1291/*2
1292* assumes that the head term of b is a multiple of the head term of a
1293* and return the multiplicant *m
1294* Frank's observation: If LM(b) = LM(a)*m, then we may actually set
1295* negative(!) exponents in the below loop. I suspect that the correct
1296* comment should be "assumes that LM(a) = LM(b)*m, for some monomial m..."
1297*/
1298poly p_Divide(poly a, poly b, const ring r)
1299{
1300  assume((p_GetComp(a,r)==p_GetComp(b,r)) || (p_GetComp(b,r)==0));
1301  int i;
1302  poly result = p_Init(r);
1303
1304  for(i=(int)r->N; i; i--)
1305    p_SetExp(result,i, p_GetExp(a,i,r)- p_GetExp(b,i,r),r);
1306  p_SetComp(result, p_GetComp(a,r) - p_GetComp(b,r),r);
1307  p_Setm(result,r);
1308  return result;
1309}
1310
1311#ifdef HAVE_RINGS   //TODO Oliver
1312
1313poly p_Div_nn(poly p, const number n, const ring r)
1314{
1315  pAssume(!n_IsZero(n,r));
1316  p_Test(p, r);
1317
1318  poly q = p;
1319  while (p != NULL)
1320  {
1321    number nc = pGetCoeff(p);
1322    pSetCoeff0(p, n_Div(nc, n, r->cf));
1323    n_Delete(&nc, r->cf);
1324    pIter(p);
1325  }
1326  p_Test(q, r);
1327  return q;
1328}
1329#endif
1330
1331/*2
1332* divides a by the monomial b, ignores monomials which are not divisible
1333* assumes that b is not NULL
1334*/
1335poly p_DivideM(poly a, poly b, const ring r)
1336{
1337  if (a==NULL) return NULL;
1338  poly result=a;
1339  poly prev=NULL;
1340  int i;
1341#ifdef HAVE_RINGS
1342  number inv=pGetCoeff(b);
1343#else
1344  number inv=n_Invers(pGetCoeff(b),r->cf);
1345#endif
1346
1347  while (a!=NULL)
1348  {
1349    if (p_DivisibleBy(b,a,r))
1350    {
1351      for(i=(int)r->N; i; i--)
1352         p_SubExp(a,i, p_GetExp(b,i,r),r);
1353      p_SubComp(a, p_GetComp(b,r),r);
1354      p_Setm(a,r);
1355      prev=a;
1356      pIter(a);
1357    }
1358    else
1359    {
1360      if (prev==NULL)
1361      {
1362        p_LmDelete(&result,r);
1363        a=result;
1364      }
1365      else
1366      {
1367        p_LmDelete(&pNext(prev),r);
1368        a=pNext(prev);
1369      }
1370    }
1371  }
1372#ifdef HAVE_RINGS
1373  if (n_IsUnit(inv,r->cf))
1374  {
1375    inv = n_Invers(inv,r->cf);
1376    p_Mult_nn(result,inv,r);
1377    n_Delete(&inv, r->cf);
1378  }
1379  else
1380  {
1381    p_Div_nn(result,inv,r);
1382  }
1383#else
1384  p_Mult_nn(result,inv,r);
1385  n_Delete(&inv, r->cf);
1386#endif
1387  p_Delete(&b, r);
1388  return result;
1389}
1390
1391/*2
1392* returns the LCM of the head terms of a and b in *m
1393*/
1394void p_Lcm(poly a, poly b, poly m, const ring r)
1395{
1396  int i;
1397  for (i=rVar(r); i; i--)
1398  {
1399    p_SetExp(m,i, si_max( p_GetExp(a,i,r), p_GetExp(b,i,r)),r);
1400  }
1401  p_SetComp(m, si_max(p_GetComp(a,r), p_GetComp(b,r)),r);
1402  /* Don't do a pSetm here, otherwise hres/lres chockes */
1403}
1404
1405/*2
1406* returns the partial differentiate of a by the k-th variable
1407* does not destroy the input
1408*/
1409poly p_Diff(poly a, int k, const ring r)
1410{
1411  poly res, f, last;
1412  number t;
1413
1414  last = res = NULL;
1415  while (a!=NULL)
1416  {
1417    if (p_GetExp(a,k,r)!=0)
1418    {
1419      f = p_LmInit(a,r);
1420      t = n_Init(p_GetExp(a,k,r),r->cf);
1421      pSetCoeff0(f,n_Mult(t,pGetCoeff(a),r->cf));
1422      n_Delete(&t,r->cf);
1423      if (n_IsZero(pGetCoeff(f),r->cf))
1424        p_LmDelete(&f,r);
1425      else
1426      {
1427        p_DecrExp(f,k,r);
1428        p_Setm(f,r);
1429        if (res==NULL)
1430        {
1431          res=last=f;
1432        }
1433        else
1434        {
1435          pNext(last)=f;
1436          last=f;
1437        }
1438      }
1439    }
1440    pIter(a);
1441  }
1442  return res;
1443}
1444
1445static poly p_DiffOpM(poly a, poly b,BOOLEAN multiply, const ring r)
1446{
1447  int i,j,s;
1448  number n,h,hh;
1449  poly p=p_One(r);
1450  n=n_Mult(pGetCoeff(a),pGetCoeff(b),r->cf);
1451  for(i=rVar(r);i>0;i--)
1452  {
1453    s=p_GetExp(b,i,r);
1454    if (s<p_GetExp(a,i,r))
1455    {
1456      n_Delete(&n,r->cf);
1457      p_LmDelete(&p,r);
1458      return NULL;
1459    }
1460    if (multiply)
1461    {
1462      for(j=p_GetExp(a,i,r); j>0;j--)
1463      {
1464        h = n_Init(s,r->cf);
1465        hh=n_Mult(n,h,r->cf);
1466        n_Delete(&h,r->cf);
1467        n_Delete(&n,r->cf);
1468        n=hh;
1469        s--;
1470      }
1471      p_SetExp(p,i,s,r);
1472    }
1473    else
1474    {
1475      p_SetExp(p,i,s-p_GetExp(a,i,r),r);
1476    }
1477  }
1478  p_Setm(p,r);
1479  /*if (multiply)*/ p_SetCoeff(p,n,r);
1480  if (n_IsZero(n,r->cf))  p=p_LmDeleteAndNext(p,r); // return NULL as p is a monomial
1481  return p;
1482}
1483
1484poly p_DiffOp(poly a, poly b,BOOLEAN multiply, const ring r)
1485{
1486  poly result=NULL;
1487  poly h;
1488  for(;a!=NULL;pIter(a))
1489  {
1490    for(h=b;h!=NULL;pIter(h))
1491    {
1492      result=p_Add_q(result,p_DiffOpM(a,h,multiply,r),r);
1493    }
1494  }
1495  return result;
1496}
1497/*2
1498* subtract p2 from p1, p1 and p2 are destroyed
1499* do not put attention on speed: the procedure is only used in the interpreter
1500*/
1501poly p_Sub(poly p1, poly p2, const ring r)
1502{
1503  return p_Add_q(p1, p_Neg(p2,r),r);
1504}
1505
1506/*3
1507* compute for a monomial m
1508* the power m^exp, exp > 1
1509* destroys p
1510*/
1511static poly p_MonPower(poly p, int exp, const ring r)
1512{
1513  int i;
1514
1515  if(!n_IsOne(pGetCoeff(p),r->cf))
1516  {
1517    number x, y;
1518    y = pGetCoeff(p);
1519    n_Power(y,exp,&x,r->cf);
1520    n_Delete(&y,r->cf);
1521    pSetCoeff0(p,x);
1522  }
1523  for (i=rVar(r); i!=0; i--)
1524  {
1525    p_MultExp(p,i, exp,r);
1526  }
1527  p_Setm(p,r);
1528  return p;
1529}
1530
1531/*3
1532* compute for monomials p*q
1533* destroys p, keeps q
1534*/
1535static void p_MonMult(poly p, poly q, const ring r)
1536{
1537  number x, y;
1538  int i;
1539
1540  y = pGetCoeff(p);
1541  x = n_Mult(y,pGetCoeff(q),r->cf);
1542  n_Delete(&y,r->cf);
1543  pSetCoeff0(p,x);
1544  //for (i=pVariables; i!=0; i--)
1545  //{
1546  //  pAddExp(p,i, pGetExp(q,i));
1547  //}
1548  //p->Order += q->Order;
1549  p_ExpVectorAdd(p,q,r);
1550}
1551
1552/*3
1553* compute for monomials p*q
1554* keeps p, q
1555*/
1556static poly p_MonMultC(poly p, poly q, const ring rr)
1557{
1558  number x;
1559  int i;
1560  poly r = p_Init(rr);
1561
1562  x = n_Mult(pGetCoeff(p),pGetCoeff(q),rr->cf);
1563  pSetCoeff0(r,x);
1564  p_ExpVectorSum(r,p, q, rr);
1565  return r;
1566}
1567
1568/*3
1569*  create binomial coef.
1570*/
1571static number* pnBin(int exp, const ring r)
1572{
1573  int e, i, h;
1574  number x, y, *bin=NULL;
1575
1576  x = n_Init(exp,r->cf);
1577  if (n_IsZero(x,r->cf))
1578  {
1579    n_Delete(&x,r->cf);
1580    return bin;
1581  }
1582  h = (exp >> 1) + 1;
1583  bin = (number *)omAlloc0(h*sizeof(number));
1584  bin[1] = x;
1585  if (exp < 4)
1586    return bin;
1587  i = exp - 1;
1588  for (e=2; e<h; e++)
1589  {
1590      x = n_Init(i,r->cf);
1591      i--;
1592      y = n_Mult(x,bin[e-1],r->cf);
1593      n_Delete(&x,r->cf);
1594      x = n_Init(e,r->cf);
1595      bin[e] = n_IntDiv(y,x,r->cf);
1596      n_Delete(&x,r->cf);
1597      n_Delete(&y,r->cf);
1598  }
1599  return bin;
1600}
1601
1602static void pnFreeBin(number *bin, int exp,const coeffs r)
1603{
1604  int e, h = (exp >> 1) + 1;
1605
1606  if (bin[1] != NULL)
1607  {
1608    for (e=1; e<h; e++)
1609      n_Delete(&(bin[e]),r);
1610  }
1611  omFreeSize((ADDRESS)bin, h*sizeof(number));
1612}
1613
1614/*
1615*  compute for a poly p = head+tail, tail is monomial
1616*          (head + tail)^exp, exp > 1
1617*          with binomial coef.
1618*/
1619static poly p_TwoMonPower(poly p, int exp, const ring r)
1620{
1621  int eh, e;
1622  long al;
1623  poly *a;
1624  poly tail, b, res, h;
1625  number x;
1626  number *bin = pnBin(exp,r);
1627
1628  tail = pNext(p);
1629  if (bin == NULL)
1630  {
1631    p_MonPower(p,exp,r);
1632    p_MonPower(tail,exp,r);
1633#ifdef PDEBUG
1634    p_Test(p,r);
1635#endif
1636    return p;
1637  }
1638  eh = exp >> 1;
1639  al = (exp + 1) * sizeof(poly);
1640  a = (poly *)omAlloc(al);
1641  a[1] = p;
1642  for (e=1; e<exp; e++)
1643  {
1644    a[e+1] = p_MonMultC(a[e],p,r);
1645  }
1646  res = a[exp];
1647  b = p_Head(tail,r);
1648  for (e=exp-1; e>eh; e--)
1649  {
1650    h = a[e];
1651    x = n_Mult(bin[exp-e],pGetCoeff(h),r->cf);
1652    p_SetCoeff(h,x,r);
1653    p_MonMult(h,b,r);
1654    res = pNext(res) = h;
1655    p_MonMult(b,tail,r);
1656  }
1657  for (e=eh; e!=0; e--)
1658  {
1659    h = a[e];
1660    x = n_Mult(bin[e],pGetCoeff(h),r->cf);
1661    p_SetCoeff(h,x,r);
1662    p_MonMult(h,b,r);
1663    res = pNext(res) = h;
1664    p_MonMult(b,tail,r);
1665  }
1666  p_LmDelete(&tail,r);
1667  pNext(res) = b;
1668  pNext(b) = NULL;
1669  res = a[exp];
1670  omFreeSize((ADDRESS)a, al);
1671  pnFreeBin(bin, exp, r->cf);
1672//  tail=res;
1673// while((tail!=NULL)&&(pNext(tail)!=NULL))
1674// {
1675//   if(nIsZero(pGetCoeff(pNext(tail))))
1676//   {
1677//     pLmDelete(&pNext(tail));
1678//   }
1679//   else
1680//     pIter(tail);
1681// }
1682#ifdef PDEBUG
1683  p_Test(res,r);
1684#endif
1685  return res;
1686}
1687
1688static poly p_Pow(poly p, int i, const ring r)
1689{
1690  poly rc = p_Copy(p,r);
1691  i -= 2;
1692  do
1693  {
1694    rc = p_Mult_q(rc,p_Copy(p,r),r);
1695    p_Normalize(rc,r);
1696    i--;
1697  }
1698  while (i != 0);
1699  return p_Mult_q(rc,p,r);
1700}
1701
1702/*2
1703* returns the i-th power of p
1704* p will be destroyed
1705*/
1706poly p_Power(poly p, int i, const ring r)
1707{
1708  poly rc=NULL;
1709
1710  if (i==0)
1711  {
1712    p_Delete(&p,r);
1713    return p_One(r);
1714  }
1715
1716  if(p!=NULL)
1717  {
1718    if ( (i > 0) && ((unsigned long ) i > (r->bitmask)))
1719    {
1720      Werror("exponent %d is too large, max. is %ld",i,r->bitmask);
1721      return NULL;
1722    }
1723    switch (i)
1724    {
1725// cannot happen, see above
1726//      case 0:
1727//      {
1728//        rc=pOne();
1729//        pDelete(&p);
1730//        break;
1731//      }
1732      case 1:
1733        rc=p;
1734        break;
1735      case 2:
1736        rc=p_Mult_q(p_Copy(p,r),p,r);
1737        break;
1738      default:
1739        if (i < 0)
1740        {
1741          p_Delete(&p,r);
1742          return NULL;
1743        }
1744        else
1745        {
1746#ifdef HAVE_PLURAL
1747          if (rIsPluralRing(r)) /* in the NC case nothing helps :-( */
1748          {
1749            int j=i;
1750            rc = p_Copy(p,r);
1751            while (j>1)
1752            {
1753              rc = p_Mult_q(p_Copy(p,r),rc,r);
1754              j--;
1755            }
1756            p_Delete(&p,r);
1757            return rc;
1758          }
1759#endif
1760          rc = pNext(p);
1761          if (rc == NULL)
1762            return p_MonPower(p,i,r);
1763          /* else: binom ?*/
1764          int char_p=rChar(r);
1765          if ((pNext(rc) != NULL)
1766#ifdef HAVE_RINGS
1767             || rField_is_Ring(r)
1768#endif
1769             )
1770            return p_Pow(p,i,r);
1771          if ((char_p==0) || (i<=char_p))
1772            return p_TwoMonPower(p,i,r);
1773          poly p_p=p_TwoMonPower(p_Copy(p,r),char_p,r);
1774          return p_Mult_q(p_Power(p,i-char_p,r),p_p,r);
1775        }
1776      /*end default:*/
1777    }
1778  }
1779  return rc;
1780}
1781
1782/* --------------------------------------------------------------------------------*/
1783/* content suff                                                                   */
1784
1785static number p_InitContent(poly ph, const ring r);
1786static number p_InitContent_a(poly ph, const ring r);
1787
1788void p_Content(poly ph, const ring r)
1789{
1790#ifdef HAVE_RINGS
1791  if (rField_is_Ring(r))
1792  {
1793    if ((ph!=NULL) && rField_has_Units(r))
1794    {
1795      number k = n_GetUnit(pGetCoeff(ph),r->cf);
1796      if (!n_IsOne(k,r->cf))
1797      {
1798        number tmpGMP = k;
1799        k = n_Invers(k,r->cf);
1800        n_Delete(&tmpGMP,r->cf);
1801        poly h = pNext(ph);
1802        p_SetCoeff(ph, n_Mult(pGetCoeff(ph), k,r->cf),r);
1803        while (h != NULL)
1804        {
1805          p_SetCoeff(h, n_Mult(pGetCoeff(h), k,r->cf),r);
1806          pIter(h);
1807        }
1808      }
1809      n_Delete(&k,r->cf);
1810    }
1811    return;
1812  }
1813#endif
1814  number h,d;
1815  poly p;
1816
1817  if(TEST_OPT_CONTENTSB) return;
1818  if(pNext(ph)==NULL)
1819  {
1820    p_SetCoeff(ph,n_Init(1,r->cf),r);
1821  }
1822  else
1823  {
1824    n_Normalize(pGetCoeff(ph),r->cf);
1825    if(!n_GreaterZero(pGetCoeff(ph),r->cf)) ph = p_Neg(ph,r);
1826    if (rField_is_Q(r))
1827    {
1828      h=p_InitContent(ph,r);
1829      p=ph;
1830    }
1831    else if ((rField_is_Extension(r))
1832    && ((rPar(r)>1)||(r->minpoly==NULL)))
1833    {
1834      h=p_InitContent_a(ph,r);
1835      p=ph;
1836    }
1837    else
1838    {
1839      h=n_Copy(pGetCoeff(ph),r->cf);
1840      p = pNext(ph);
1841    }
1842    while (p!=NULL)
1843    {
1844      n_Normalize(pGetCoeff(p),r->cf);
1845      d=n_Gcd(h,pGetCoeff(p),r->cf);
1846      n_Delete(&h,r->cf);
1847      h = d;
1848      if(n_IsOne(h,r->cf))
1849      {
1850        break;
1851      }
1852      pIter(p);
1853    }
1854    p = ph;
1855    //number tmp;
1856    if(!n_IsOne(h,r->cf))
1857    {
1858      while (p!=NULL)
1859      {
1860        //d = nDiv(pGetCoeff(p),h);
1861        //tmp = nIntDiv(pGetCoeff(p),h);
1862        //if (!nEqual(d,tmp))
1863        //{
1864        //  StringSetS("** div0:");nWrite(pGetCoeff(p));StringAppendS("/");
1865        //  nWrite(h);StringAppendS("=");nWrite(d);StringAppendS(" int:");
1866        //  nWrite(tmp);Print(StringAppendS("\n"));
1867        //}
1868        //nDelete(&tmp);
1869        d = n_IntDiv(pGetCoeff(p),h,r->cf);
1870        p_SetCoeff(p,d,r);
1871        pIter(p);
1872      }
1873    }
1874    n_Delete(&h,r->cf);
1875#ifdef HAVE_FACTORY
1876    if ( (nGetChar() == 1) || (nGetChar() < 0) ) /* Q[a],Q(a),Zp[a],Z/p(a) */
1877    {
1878      singclap_divide_content(ph);
1879      if(!n_GreaterZero(pGetCoeff(ph),r->cf)) ph = p_Neg(ph,r);
1880    }
1881#endif
1882    if (rField_is_Q_a(r))
1883    {
1884      number hzz = nlInit(1, r->cf);
1885      h = nlInit(1, r->cf);
1886      p=ph;
1887      Werror("longalg missing");
1888      #if 0
1889      while (p!=NULL)
1890      { // each monom: coeff in Q_a
1891        lnumber c_n_n=(lnumber)pGetCoeff(p);
1892        poly c_n=c_n_n->z;
1893        while (c_n!=NULL)
1894        { // each monom: coeff in Q
1895          d=nlLcm(hzz,pGetCoeff(c_n),r->algring->cf);
1896          n_Delete(&hzz,r->algring->cf);
1897          hzz=d;
1898          pIter(c_n);
1899        }
1900        c_n=c_n_n->n;
1901        while (c_n!=NULL)
1902        { // each monom: coeff in Q
1903          d=nlLcm(h,pGetCoeff(c_n),r->algring->cf);
1904          n_Delete(&h,r->algring->cf);
1905          h=d;
1906          pIter(c_n);
1907        }
1908        pIter(p);
1909      }
1910      /* hzz contains the 1/lcm of all denominators in c_n_n->z*/
1911      /* h contains the 1/lcm of all denominators in c_n_n->n*/
1912      number htmp=nlInvers(h,r->algring->cf);
1913      number hzztmp=nlInvers(hzz,r->algring->cf);
1914      number hh=nlMult(hzz,h,r->algring->cf);
1915      nlDelete(&hzz,r->algring->cf);
1916      nlDelete(&h,r->algring->cf);
1917      number hg=nlGcd(hzztmp,htmp,r->algring->cf);
1918      nlDelete(&hzztmp,r->algring->cf);
1919      nlDelete(&htmp,r->algring->cf);
1920      h=nlMult(hh,hg,r->algring->cf);
1921      nlDelete(&hg,r->algring->cf);
1922      nlDelete(&hh,r->algring->cf);
1923      nlNormalize(h,r->algring->cf);
1924      if(!nlIsOne(h,r->algring->cf))
1925      {
1926        p=ph;
1927        while (p!=NULL)
1928        { // each monom: coeff in Q_a
1929          lnumber c_n_n=(lnumber)pGetCoeff(p);
1930          poly c_n=c_n_n->z;
1931          while (c_n!=NULL)
1932          { // each monom: coeff in Q
1933            d=nlMult(h,pGetCoeff(c_n),r->algring->cf);
1934            nlNormalize(d,r->algring->cf);
1935            nlDelete(&pGetCoeff(c_n),r->algring->cf);
1936            pGetCoeff(c_n)=d;
1937            pIter(c_n);
1938          }
1939          c_n=c_n_n->n;
1940          while (c_n!=NULL)
1941          { // each monom: coeff in Q
1942            d=nlMult(h,pGetCoeff(c_n),r->algring->cf);
1943            nlNormalize(d,r->algring->cf);
1944            nlDelete(&pGetCoeff(c_n),r->algring->cf);
1945            pGetCoeff(c_n)=d;
1946            pIter(c_n);
1947          }
1948          pIter(p);
1949        }
1950      }
1951      nlDelete(&h,r->algring->cf);
1952      #endif
1953    }
1954  }
1955}
1956#if 0 // currently not used
1957void p_SimpleContent(poly ph,int smax, const ring r)
1958{
1959  if(TEST_OPT_CONTENTSB) return;
1960  if (ph==NULL) return;
1961  if (pNext(ph)==NULL)
1962  {
1963    p_SetCoeff(ph,n_Init(1,r_cf),r);
1964    return;
1965  }
1966  if ((pNext(pNext(ph))==NULL)||(!rField_is_Q(r)))
1967  {
1968    return;
1969  }
1970  number d=p_InitContent(ph,r);
1971  if (nlSize(d,r->cf)<=smax)
1972  {
1973    //if (TEST_OPT_PROT) PrintS("G");
1974    return;
1975  }
1976  poly p=ph;
1977  number h=d;
1978  if (smax==1) smax=2;
1979  while (p!=NULL)
1980  {
1981#if 0
1982    d=nlGcd(h,pGetCoeff(p),r->cf);
1983    nlDelete(&h,r->cf);
1984    h = d;
1985#else
1986    nlInpGcd(h,pGetCoeff(p),r->cf);
1987#endif
1988    if(nlSize(h,r->cf)<smax)
1989    {
1990      //if (TEST_OPT_PROT) PrintS("g");
1991      return;
1992    }
1993    pIter(p);
1994  }
1995  p = ph;
1996  if (!nlGreaterZero(pGetCoeff(p),r->cf)) h=nlNeg(h,r->cf);
1997  if(nlIsOne(h,r->cf)) return;
1998  //if (TEST_OPT_PROT) PrintS("c");
1999  while (p!=NULL)
2000  {
2001#if 1
2002    d = nlIntDiv(pGetCoeff(p),h,r->cf);
2003    p_SetCoeff(p,d,r);
2004#else
2005    nlInpIntDiv(pGetCoeff(p),h,r->cf);
2006#endif
2007    pIter(p);
2008  }
2009  nlDelete(&h,r->cf);
2010}
2011#endif
2012
2013static number p_InitContent(poly ph, const ring r)
2014// only for coefficients in Q
2015#if 0
2016{
2017  assume(!TEST_OPT_CONTENTSB);
2018  assume(ph!=NULL);
2019  assume(pNext(ph)!=NULL);
2020  assume(rField_is_Q(r));
2021  if (pNext(pNext(ph))==NULL)
2022  {
2023    return nlGetNom(pGetCoeff(pNext(ph)),r->cf);
2024  }
2025  poly p=ph;
2026  number n1=nlGetNom(pGetCoeff(p),r->cf);
2027  pIter(p);
2028  number n2=nlGetNom(pGetCoeff(p),r->cf);
2029  pIter(p);
2030  number d;
2031  number t;
2032  loop
2033  {
2034    nlNormalize(pGetCoeff(p),r->cf);
2035    t=nlGetNom(pGetCoeff(p),r->cf);
2036    if (nlGreaterZero(t,r->cf))
2037      d=nlAdd(n1,t,r->cf);
2038    else
2039      d=nlSub(n1,t,r->cf);
2040    nlDelete(&t,r->cf);
2041    nlDelete(&n1,r->cf);
2042    n1=d;
2043    pIter(p);
2044    if (p==NULL) break;
2045    nlNormalize(pGetCoeff(p),r->cf);
2046    t=nlGetNom(pGetCoeff(p),r->cf);
2047    if (nlGreaterZero(t,r->cf))
2048      d=nlAdd(n2,t,r->cf);
2049    else
2050      d=nlSub(n2,t,r->cf);
2051    nlDelete(&t,r->cf);
2052    nlDelete(&n2,r->cf);
2053    n2=d;
2054    pIter(p);
2055    if (p==NULL) break;
2056  }
2057  d=nlGcd(n1,n2,r->cf);
2058  nlDelete(&n1,r->cf);
2059  nlDelete(&n2,r->cf);
2060  return d;
2061}
2062#else
2063{
2064  number d=pGetCoeff(ph);
2065  if(SR_HDL(d)&SR_INT) return d;
2066  int s=mpz_size1(d->z);
2067  int s2=-1;
2068  number d2;
2069  loop
2070  {
2071    pIter(ph);
2072    if(ph==NULL)
2073    {
2074      if (s2==-1) return nlCopy(d,r->cf);
2075      break;
2076    }
2077    if (SR_HDL(pGetCoeff(ph))&SR_INT)
2078    {
2079      s2=s;
2080      d2=d;
2081      s=0;
2082      d=pGetCoeff(ph);
2083      if (s2==0) break;
2084    }
2085    else
2086    if (mpz_size1((pGetCoeff(ph)->z))<=s)
2087    {
2088      s2=s;
2089      d2=d;
2090      d=pGetCoeff(ph);
2091      s=mpz_size1(d->z);
2092    }
2093  }
2094  return nlGcd(d,d2,r->cf);
2095}
2096#endif
2097
2098number p_InitContent_a(poly ph, const ring r)
2099// only for coefficients in K(a) anf K(a,...)
2100{
2101  number d=pGetCoeff(ph);
2102  int s=n_ParDeg(d,r->cf);
2103  if (s /* n_ParDeg(d)*/ <=1) return n_Copy(d,r->cf);
2104  int s2=-1;
2105  number d2;
2106  int ss;
2107  loop
2108  {
2109    pIter(ph);
2110    if(ph==NULL)
2111    {
2112      if (s2==-1) return n_Copy(d,r->cf);
2113      break;
2114    }
2115    if ((ss=n_ParDeg(pGetCoeff(ph),r->cf))<s)
2116    {
2117      s2=s;
2118      d2=d;
2119      s=ss;
2120      d=pGetCoeff(ph);
2121      if (s2<=1) break;
2122    }
2123  }
2124  return n_Gcd(d,d2,r->cf);
2125}
2126
2127
2128//void pContent(poly ph)
2129//{
2130//  number h,d;
2131//  poly p;
2132//
2133//  p = ph;
2134//  if(pNext(p)==NULL)
2135//  {
2136//    pSetCoeff(p,nInit(1));
2137//  }
2138//  else
2139//  {
2140//#ifdef PDEBUG
2141//    if (!pTest(p)) return;
2142//#endif
2143//    nNormalize(pGetCoeff(p));
2144//    if(!nGreaterZero(pGetCoeff(ph)))
2145//    {
2146//      ph = pNeg(ph);
2147//      nNormalize(pGetCoeff(p));
2148//    }
2149//    h=pGetCoeff(p);
2150//    pIter(p);
2151//    while (p!=NULL)
2152//    {
2153//      nNormalize(pGetCoeff(p));
2154//      if (nGreater(h,pGetCoeff(p))) h=pGetCoeff(p);
2155//      pIter(p);
2156//    }
2157//    h=nCopy(h);
2158//    p=ph;
2159//    while (p!=NULL)
2160//    {
2161//      d=nGcd(h,pGetCoeff(p));
2162//      nDelete(&h);
2163//      h = d;
2164//      if(nIsOne(h))
2165//      {
2166//        break;
2167//      }
2168//      pIter(p);
2169//    }
2170//    p = ph;
2171//    //number tmp;
2172//    if(!nIsOne(h))
2173//    {
2174//      while (p!=NULL)
2175//      {
2176//        d = nIntDiv(pGetCoeff(p),h);
2177//        pSetCoeff(p,d);
2178//        pIter(p);
2179//      }
2180//    }
2181//    nDelete(&h);
2182//#ifdef HAVE_FACTORY
2183//    if ( (nGetChar() == 1) || (nGetChar() < 0) ) /* Q[a],Q(a),Zp[a],Z/p(a) */
2184//    {
2185//      pTest(ph);
2186//      singclap_divide_content(ph);
2187//      pTest(ph);
2188//    }
2189//#endif
2190//  }
2191//}
2192#if 0
2193void p_Content(poly ph, const ring r)
2194{
2195  number h,d;
2196  poly p;
2197
2198  if(pNext(ph)==NULL)
2199  {
2200    p_SetCoeff(ph,n_Init(1,r->cf),r);
2201  }
2202  else
2203  {
2204    n_Normalize(pGetCoeff(ph),r->cf);
2205    if(!n_GreaterZero(pGetCoeff(ph),r->cf)) ph = p_Neg(ph,r);
2206    h=n_Copy(pGetCoeff(ph),r->cf);
2207    p = pNext(ph);
2208    while (p!=NULL)
2209    {
2210      n_Normalize(pGetCoeff(p),r->cf);
2211      d=n_Gcd(h,pGetCoeff(p),r->cf);
2212      n_Delete(&h,r->cf);
2213      h = d;
2214      if(n_IsOne(h,r->cf))
2215      {
2216        break;
2217      }
2218      pIter(p);
2219    }
2220    p = ph;
2221    //number tmp;
2222    if(!n_IsOne(h,r->cf))
2223    {
2224      while (p!=NULL)
2225      {
2226        //d = nDiv(pGetCoeff(p),h);
2227        //tmp = nIntDiv(pGetCoeff(p),h);
2228        //if (!nEqual(d,tmp))
2229        //{
2230        //  StringSetS("** div0:");nWrite(pGetCoeff(p));StringAppendS("/");
2231        //  nWrite(h);StringAppendS("=");nWrite(d);StringAppendS(" int:");
2232        //  nWrite(tmp);Print(StringAppendS("\n"));
2233        //}
2234        //nDelete(&tmp);
2235        d = n_IntDiv(pGetCoeff(p),h,r->cf);
2236        p_SetCoeff(p,d,r->cf);
2237        pIter(p);
2238      }
2239    }
2240    n_Delete(&h,r->cf);
2241#ifdef HAVE_FACTORY
2242    //if ( (n_GetChar(r) == 1) || (n_GetChar(r) < 0) ) /* Q[a],Q(a),Zp[a],Z/p(a) */
2243    //{
2244    //  singclap_divide_content(ph);
2245    //  if(!n_GreaterZero(pGetCoeff(ph),r)) ph = p_Neg(ph,r);
2246    //}
2247#endif
2248  }
2249}
2250#endif
2251/* ---------------------------------------------------------------------------*/
2252/* cleardenom suff                                                           */
2253poly p_Cleardenom(poly ph, const ring r)
2254{
2255  poly start=ph;
2256  number d, h;
2257  poly p;
2258
2259#ifdef HAVE_RINGS
2260  if (rField_is_Ring(r))
2261  {
2262    p_Content(ph,r);
2263    return start;
2264  }
2265#endif
2266  if (rField_is_Zp(r) && TEST_OPT_INTSTRATEGY) return start;
2267  p = ph;
2268  if(pNext(p)==NULL)
2269  {
2270    if (TEST_OPT_CONTENTSB)
2271    {
2272      number n=n_GetDenom(pGetCoeff(p),r->cf);
2273      if (!n_IsOne(n,r->cf))
2274      {
2275        number nn=n_Mult(pGetCoeff(p),n,r->cf);
2276        n_Normalize(nn,r->cf);
2277        p_SetCoeff(p,nn,r);
2278      }
2279      n_Delete(&n,r->cf);
2280    }
2281    else
2282      p_SetCoeff(p,n_Init(1,r->cf),r);
2283  }
2284  else
2285  {
2286    h = n_Init(1,r->cf);
2287    while (p!=NULL)
2288    {
2289      n_Normalize(pGetCoeff(p),r->cf);
2290      d=n_Lcm(h,pGetCoeff(p),r->cf);
2291      n_Delete(&h,r->cf);
2292      h=d;
2293      pIter(p);
2294    }
2295    /* contains the 1/lcm of all denominators */
2296    if(!n_IsOne(h,r->cf))
2297    {
2298      p = ph;
2299      while (p!=NULL)
2300      {
2301        /* should be:
2302        * number hh;
2303        * nGetDenom(p->coef,&hh);
2304        * nMult(&h,&hh,&d);
2305        * nNormalize(d);
2306        * nDelete(&hh);
2307        * nMult(d,p->coef,&hh);
2308        * nDelete(&d);
2309        * nDelete(&(p->coef));
2310        * p->coef =hh;
2311        */
2312        d=n_Mult(h,pGetCoeff(p),r->cf);
2313        n_Normalize(d,r->cf);
2314        p_SetCoeff(p,d,r);
2315        pIter(p);
2316      }
2317      n_Delete(&h,r->cf);
2318      if (n_GetChar(r->cf)==1)
2319      {
2320        loop
2321        {
2322          h = n_Init(1,r->cf);
2323          p=ph;
2324          while (p!=NULL)
2325          {
2326            d=n_Lcm(h,pGetCoeff(p),r->cf);
2327            n_Delete(&h,r->cf);
2328            h=d;
2329            pIter(p);
2330          }
2331          /* contains the 1/lcm of all denominators */
2332          if(!n_IsOne(h,r->cf))
2333          {
2334            p = ph;
2335            while (p!=NULL)
2336            {
2337              /* should be:
2338              * number hh;
2339              * nGetDenom(p->coef,&hh);
2340              * nMult(&h,&hh,&d);
2341              * nNormalize(d);
2342              * nDelete(&hh);
2343              * nMult(d,p->coef,&hh);
2344              * nDelete(&d);
2345              * nDelete(&(p->coef));
2346              * p->coef =hh;
2347              */
2348              d=n_Mult(h,pGetCoeff(p),r->cf);
2349              n_Normalize(d,r->cf);
2350              p_SetCoeff(p,d,r);
2351              pIter(p);
2352            }
2353            n_Delete(&h,r->cf);
2354          }
2355          else
2356          {
2357            n_Delete(&h,r->cf);
2358            break;
2359          }
2360        }
2361      }
2362    }
2363    if (h!=NULL) n_Delete(&h,r->cf);
2364
2365    p_Content(ph,r);
2366#ifdef HAVE_RATGRING
2367    if (rIsRatGRing(r))
2368    {
2369      /* quick unit detection in the rational case is done in gr_nc_bba */
2370      pContentRat(ph);
2371      start=ph;
2372    }
2373#endif
2374  }
2375  return start;
2376}
2377
2378void p_Cleardenom_n(poly ph,const ring r,number &c)
2379{
2380  number d, h;
2381  poly p;
2382
2383  p = ph;
2384  if(pNext(p)==NULL)
2385  {
2386    c=n_Invers(pGetCoeff(p),r->cf);
2387    p_SetCoeff(p,n_Init(1,r->cf),r);
2388  }
2389  else
2390  {
2391    h = n_Init(1,r->cf);
2392    while (p!=NULL)
2393    {
2394      n_Normalize(pGetCoeff(p),r->cf);
2395      d=n_Lcm(h,pGetCoeff(p),r->cf);
2396      n_Delete(&h,r->cf);
2397      h=d;
2398      pIter(p);
2399    }
2400    c=h;
2401    /* contains the 1/lcm of all denominators */
2402    if(!n_IsOne(h,r->cf))
2403    {
2404      p = ph;
2405      while (p!=NULL)
2406      {
2407        /* should be:
2408        * number hh;
2409        * nGetDenom(p->coef,&hh);
2410        * nMult(&h,&hh,&d);
2411        * nNormalize(d);
2412        * nDelete(&hh);
2413        * nMult(d,p->coef,&hh);
2414        * nDelete(&d);
2415        * nDelete(&(p->coef));
2416        * p->coef =hh;
2417        */
2418        d=n_Mult(h,pGetCoeff(p),r->cf);
2419        n_Normalize(d,r->cf);
2420        p_SetCoeff(p,d,r);
2421        pIter(p);
2422      }
2423      if (rField_is_Q_a(r))
2424      {
2425        loop
2426        {
2427          h = n_Init(1,r->cf);
2428          p=ph;
2429          while (p!=NULL)
2430          {
2431            d=n_Lcm(h,pGetCoeff(p),r->cf);
2432            n_Delete(&h,r->cf);
2433            h=d;
2434            pIter(p);
2435          }
2436          /* contains the 1/lcm of all denominators */
2437          if(!n_IsOne(h,r->cf))
2438          {
2439            p = ph;
2440            while (p!=NULL)
2441            {
2442              /* should be:
2443              * number hh;
2444              * nGetDenom(p->coef,&hh);
2445              * nMult(&h,&hh,&d);
2446              * nNormalize(d);
2447              * nDelete(&hh);
2448              * nMult(d,p->coef,&hh);
2449              * nDelete(&d);
2450              * nDelete(&(p->coef));
2451              * p->coef =hh;
2452              */
2453              d=n_Mult(h,pGetCoeff(p),r->cf);
2454              n_Normalize(d,r->cf);
2455              p_SetCoeff(p,d,r);
2456              pIter(p);
2457            }
2458            number t=n_Mult(c,h,r->cf);
2459            n_Delete(&c,r->cf);
2460            c=t;
2461          }
2462          else
2463          {
2464            break;
2465          }
2466          n_Delete(&h,r->cf);
2467        }
2468      }
2469    }
2470  }
2471}
2472
2473number p_GetAllDenom(poly ph, const ring r)
2474{
2475  number d=n_Init(1,r->cf);
2476  poly p = ph;
2477
2478  while (p!=NULL)
2479  {
2480    number h=n_GetDenom(pGetCoeff(p),r->cf);
2481    if (!n_IsOne(h,r->cf))
2482    {
2483      number dd=n_Mult(d,h,r->cf);
2484      n_Delete(&d,r->cf);
2485      d=dd;
2486    }
2487    n_Delete(&h,r->cf);
2488    pIter(p);
2489  }
2490  return d;
2491}
2492
2493int p_Size(poly p, const ring r)
2494{
2495  int count = 0;
2496  while ( p != NULL )
2497  {
2498    count+= n_Size( pGetCoeff( p ), r->cf );
2499    pIter( p );
2500  }
2501  return count;
2502}
2503
2504/*2
2505*make p homogeneous by multiplying the monomials by powers of x_varnum
2506*assume: deg(var(varnum))==1
2507*/
2508poly p_Homogen (poly p, int varnum, const ring r)
2509{
2510  pFDegProc deg;
2511  if (r->pLexOrder && (r->order[0]==ringorder_lp))
2512    deg=p_Totaldegree;
2513  else
2514    deg=pFDeg;
2515
2516  poly q=NULL, qn;
2517  int  o,ii;
2518  sBucket_pt bp;
2519
2520  if (p!=NULL)
2521  {
2522    if ((varnum < 1) || (varnum > rVar(r)))
2523    {
2524      return NULL;
2525    }
2526    o=deg(p,r);
2527    q=pNext(p);
2528    while (q != NULL)
2529    {
2530      ii=deg(q,r);
2531      if (ii>o) o=ii;
2532      pIter(q);
2533    }
2534    q = p_Copy(p,r);
2535    bp = sBucketCreate(r);
2536    while (q != NULL)
2537    {
2538      ii = o-deg(q,r);
2539      if (ii!=0)
2540      {
2541        p_AddExp(q,varnum, (long)ii,r);
2542        p_Setm(q,r);
2543      }
2544      qn = pNext(q);
2545      pNext(q) = NULL;
2546      sBucket_Add_p(bp, q, 1);
2547      q = qn;
2548    }
2549    sBucketDestroyAdd(bp, &q, &ii);
2550  }
2551  return q;
2552}
2553
2554/*2
2555*tests if p is homogeneous with respect to the actual weigths
2556*/
2557BOOLEAN p_IsHomogeneous (poly p, const ring r)
2558{
2559  poly qp=p;
2560  int o;
2561
2562  if ((p == NULL) || (pNext(p) == NULL)) return TRUE;
2563  pFDegProc d;
2564  if (r->pLexOrder && (r->order[0]==ringorder_lp))
2565    d=p_Totaldegree;
2566  else
2567    d=pFDeg;
2568  o = d(p,r);
2569  do
2570  {
2571    if (d(qp,r) != o) return FALSE;
2572    pIter(qp);
2573  }
2574  while (qp != NULL);
2575  return TRUE;
2576}
2577
2578/*----------utilities for syzygies--------------*/
2579BOOLEAN   p_VectorHasUnitB(poly p, int * k, const ring r)
2580{
2581  poly q=p,qq;
2582  int i;
2583
2584  while (q!=NULL)
2585  {
2586    if (p_LmIsConstantComp(q,r))
2587    {
2588      i = p_GetComp(q,r);
2589      qq = p;
2590      while ((qq != q) && (p_GetComp(qq,r) != i)) pIter(qq);
2591      if (qq == q)
2592      {
2593        *k = i;
2594        return TRUE;
2595      }
2596      else
2597        pIter(q);
2598    }
2599    else pIter(q);
2600  }
2601  return FALSE;
2602}
2603
2604void   p_VectorHasUnit(poly p, int * k, int * len, const ring r)
2605{
2606  poly q=p,qq;
2607  int i,j=0;
2608
2609  *len = 0;
2610  while (q!=NULL)
2611  {
2612    if (p_LmIsConstantComp(q,r))
2613    {
2614      i = p_GetComp(q,r);
2615      qq = p;
2616      while ((qq != q) && (p_GetComp(qq,r) != i)) pIter(qq);
2617      if (qq == q)
2618      {
2619       j = 0;
2620       while (qq!=NULL)
2621       {
2622         if (p_GetComp(qq,r)==i) j++;
2623        pIter(qq);
2624       }
2625       if ((*len == 0) || (j<*len))
2626       {
2627         *len = j;
2628         *k = i;
2629       }
2630      }
2631    }
2632    pIter(q);
2633  }
2634}
2635
2636poly p_TakeOutComp1(poly * p, int k, const ring r)
2637{
2638  poly q = *p;
2639
2640  if (q==NULL) return NULL;
2641
2642  poly qq=NULL,result = NULL;
2643
2644  if (p_GetComp(q,r)==k)
2645  {
2646    result = q; /* *p */
2647    while ((q!=NULL) && (p_GetComp(q,r)==k))
2648    {
2649      p_SetComp(q,0,r);
2650      p_SetmComp(q,r);
2651      qq = q;
2652      pIter(q);
2653    }
2654    *p = q;
2655    pNext(qq) = NULL;
2656  }
2657  if (q==NULL) return result;
2658//  if (pGetComp(q) > k) pGetComp(q)--;
2659  while (pNext(q)!=NULL)
2660  {
2661    if (p_GetComp(pNext(q),r)==k)
2662    {
2663      if (result==NULL)
2664      {
2665        result = pNext(q);
2666        qq = result;
2667      }
2668      else
2669      {
2670        pNext(qq) = pNext(q);
2671        pIter(qq);
2672      }
2673      pNext(q) = pNext(pNext(q));
2674      pNext(qq) =NULL;
2675      p_SetComp(qq,0,r);
2676      p_SetmComp(qq,r);
2677    }
2678    else
2679    {
2680      pIter(q);
2681//      if (pGetComp(q) > k) pGetComp(q)--;
2682    }
2683  }
2684  return result;
2685}
2686
2687poly p_TakeOutComp(poly * p, int k, const ring r)
2688{
2689  poly q = *p,qq=NULL,result = NULL;
2690
2691  if (q==NULL) return NULL;
2692  BOOLEAN use_setmcomp=rOrd_SetCompRequiresSetm(r);
2693  if (p_GetComp(q,r)==k)
2694  {
2695    result = q;
2696    do
2697    {
2698      p_SetComp(q,0,r);
2699      if (use_setmcomp) p_SetmComp(q,r);
2700      qq = q;
2701      pIter(q);
2702    }
2703    while ((q!=NULL) && (p_GetComp(q,r)==k));
2704    *p = q;
2705    pNext(qq) = NULL;
2706  }
2707  if (q==NULL) return result;
2708  if (p_GetComp(q,r) > k)
2709  {
2710    p_SubComp(q,1,r);
2711    if (use_setmcomp) p_SetmComp(q,r);
2712  }
2713  poly pNext_q;
2714  while ((pNext_q=pNext(q))!=NULL)
2715  {
2716    if (p_GetComp(pNext_q,r)==k)
2717    {
2718      if (result==NULL)
2719      {
2720        result = pNext_q;
2721        qq = result;
2722      }
2723      else
2724      {
2725        pNext(qq) = pNext_q;
2726        pIter(qq);
2727      }
2728      pNext(q) = pNext(pNext_q);
2729      pNext(qq) =NULL;
2730      p_SetComp(qq,0,r);
2731      if (use_setmcomp) p_SetmComp(qq,r);
2732    }
2733    else
2734    {
2735      /*pIter(q);*/ q=pNext_q;
2736      if (p_GetComp(q,r) > k)
2737      {
2738        p_SubComp(q,1,r);
2739        if (use_setmcomp) p_SetmComp(q,r);
2740      }
2741    }
2742  }
2743  return result;
2744}
2745
2746// Splits *p into two polys: *q which consists of all monoms with
2747// component == comp and *p of all other monoms *lq == pLength(*q)
2748void p_TakeOutComp(poly *r_p, long comp, poly *r_q, int *lq, const ring r)
2749{
2750  spolyrec pp, qq;
2751  poly p, q, p_prev;
2752  int l = 0;
2753
2754#ifdef HAVE_ASSUME
2755  int lp = pLength(*r_p);
2756#endif
2757
2758  pNext(&pp) = *r_p;
2759  p = *r_p;
2760  p_prev = &pp;
2761  q = &qq;
2762
2763  while(p != NULL)
2764  {
2765    while (p_GetComp(p,r) == comp)
2766    {
2767      pNext(q) = p;
2768      pIter(q);
2769      p_SetComp(p, 0,r);
2770      p_SetmComp(p,r);
2771      pIter(p);
2772      l++;
2773      if (p == NULL)
2774      {
2775        pNext(p_prev) = NULL;
2776        goto Finish;
2777      }
2778    }
2779    pNext(p_prev) = p;
2780    p_prev = p;
2781    pIter(p);
2782  }
2783
2784  Finish:
2785  pNext(q) = NULL;
2786  *r_p = pNext(&pp);
2787  *r_q = pNext(&qq);
2788  *lq = l;
2789#ifdef HAVE_ASSUME
2790  assume(pLength(*r_p) + pLength(*r_q) == lp);
2791#endif
2792  p_Test(*r_p,r);
2793  p_Test(*r_q,r);
2794}
2795
2796void p_DeleteComp(poly * p,int k, const ring r)
2797{
2798  poly q;
2799
2800  while ((*p!=NULL) && (p_GetComp(*p,r)==k)) p_LmDelete(p,r);
2801  if (*p==NULL) return;
2802  q = *p;
2803  if (p_GetComp(q,r)>k)
2804  {
2805    p_SubComp(q,1,r);
2806    p_SetmComp(q,r);
2807  }
2808  while (pNext(q)!=NULL)
2809  {
2810    if (p_GetComp(pNext(q),r)==k)
2811      p_LmDelete(&(pNext(q)),r);
2812    else
2813    {
2814      pIter(q);
2815      if (p_GetComp(q,r)>k)
2816      {
2817        p_SubComp(q,1,r);
2818        p_SetmComp(q,r);
2819      }
2820    }
2821  }
2822}
2823/* -------------------------------------------------------- */
2824/*2
2825* change all global variables to fit the description of the new ring
2826*/
2827
2828void p_SetGlobals(const ring r, BOOLEAN complete)
2829{
2830  int i;
2831  if (r->ppNoether!=NULL) p_Delete(&r->ppNoether,r);
2832
2833  if (complete)
2834  {
2835    test &= ~ TEST_RINGDEP_OPTS;
2836    test |= r->options;
2837  }
2838}
2839//
2840// resets the pFDeg and pLDeg: if pLDeg is not given, it is
2841// set to currRing->pLDegOrig, i.e. to the respective LDegProc which
2842// only uses pFDeg (and not pDeg, or pTotalDegree, etc)
2843void pSetDegProcs(ring r, pFDegProc new_FDeg, pLDegProc new_lDeg)
2844{
2845  assume(new_FDeg != NULL);
2846  r->pFDeg = new_FDeg;
2847
2848  if (new_lDeg == NULL)
2849    new_lDeg = r->pLDegOrig;
2850
2851  r->pLDeg = new_lDeg;
2852}
2853
2854// restores pFDeg and pLDeg:
2855void pRestoreDegProcs(ring r, pFDegProc old_FDeg, pLDegProc old_lDeg)
2856{
2857  assume(old_FDeg != NULL && old_lDeg != NULL);
2858  r->pFDeg = old_FDeg;
2859  r->pLDeg = old_lDeg;
2860}
2861
2862/*-------- several access procedures to monomials -------------------- */
2863/*
2864* the module weights for std
2865*/
2866static pFDegProc pOldFDeg;
2867static pLDegProc pOldLDeg;
2868static intvec * pModW;
2869static BOOLEAN pOldLexOrder;
2870
2871static long pModDeg(poly p, ring r)
2872{
2873  long d=pOldFDeg(p, r);
2874  int c=p_GetComp(p, r);
2875  if ((c>0) && ((r->pModW)->range(c-1))) d+= (*(r->pModW))[c-1];
2876  return d;
2877  //return pOldFDeg(p, r)+(*pModW)[p_GetComp(p, r)-1];
2878}
2879
2880void p_SetModDeg(intvec *w, ring r)
2881{
2882  if (w!=NULL)
2883  {
2884    r->pModW = w;
2885    pOldFDeg = r->pFDeg;
2886    pOldLDeg = r->pLDeg;
2887    pOldLexOrder = r->pLexOrder;
2888    pSetDegProcs(r,pModDeg);
2889    r->pLexOrder = TRUE;
2890  }
2891  else
2892  {
2893    r->pModW = NULL;
2894    pRestoreDegProcs(r,pOldFDeg, pOldLDeg);
2895    r->pLexOrder = pOldLexOrder;
2896  }
2897}
2898
2899/*2
2900* handle memory request for sets of polynomials (ideals)
2901* l is the length of *p, increment is the difference (may be negative)
2902*/
2903void pEnlargeSet(poly* *p, int l, int increment)
2904{
2905  poly* h;
2906
2907  h=(poly*)omReallocSize((poly*)*p,l*sizeof(poly),(l+increment)*sizeof(poly));
2908  if (increment>0)
2909  {
2910    //for (i=l; i<l+increment; i++)
2911    //  h[i]=NULL;
2912    memset(&(h[l]),0,increment*sizeof(poly));
2913  }
2914  *p=h;
2915}
2916
2917/*2
2918*divides p1 by its leading coefficient
2919*/
2920void p_Norm(poly p1, const ring r)
2921{
2922#ifdef HAVE_RINGS
2923  if (rField_is_Ring(r))
2924  {
2925    if (!nIsUnit(pGetCoeff(p1))) return;
2926    // Werror("p_Norm not possible in the case of coefficient rings.");
2927  }
2928  else
2929#endif
2930  if (p1!=NULL)
2931  {
2932    if (pNext(p1)==NULL)
2933    {
2934      p_SetCoeff(p1,n_Init(1,r->cf),r);
2935      return;
2936    }
2937    poly h;
2938    if (!n_IsOne(pGetCoeff(p1),r->cf))
2939    {
2940      number k, c;
2941      n_Normalize(pGetCoeff(p1),r->cf);
2942      k = pGetCoeff(p1);
2943      c = n_Init(1,r->cf);
2944      pSetCoeff0(p1,c);
2945      h = pNext(p1);
2946      while (h!=NULL)
2947      {
2948        c=n_Div(pGetCoeff(h),k,r->cf);
2949        // no need to normalize: Z/p, R
2950        // normalize already in nDiv: Q_a, Z/p_a
2951        // remains: Q
2952        if (rField_is_Q(r) && (!n_IsOne(c,r->cf))) n_Normalize(c,r->cf);
2953        p_SetCoeff(h,c,r);
2954        pIter(h);
2955      }
2956      n_Delete(&k,r->cf);
2957    }
2958    else
2959    {
2960      //if (r->cf->cfNormalize != nDummy2) //TODO: OPTIMIZE
2961      {
2962        h = pNext(p1);
2963        while (h!=NULL)
2964        {
2965          n_Normalize(pGetCoeff(h),r->cf);
2966          pIter(h);
2967        }
2968      }
2969    }
2970  }
2971}
2972
2973/*2
2974*normalize all coefficients
2975*/
2976void p_Normalize(poly p,const ring r)
2977{
2978  if (rField_has_simple_inverse(r)) return; /* Z/p, GF(p,n), R, long R/C */
2979  while (p!=NULL)
2980  {
2981#ifdef LDEBUG
2982    if (currRing==r) {nTest(pGetCoeff(p));}
2983#endif
2984    n_Normalize(pGetCoeff(p),r->cf);
2985    pIter(p);
2986  }
2987}
2988
2989// splits p into polys with Exp(n) == 0 and Exp(n) != 0
2990// Poly with Exp(n) != 0 is reversed
2991static void p_SplitAndReversePoly(poly p, int n, poly *non_zero, poly *zero, const ring r)
2992{
2993  if (p == NULL)
2994  {
2995    *non_zero = NULL;
2996    *zero = NULL;
2997    return;
2998  }
2999  spolyrec sz;
3000  poly z, n_z, next;
3001  z = &sz;
3002  n_z = NULL;
3003
3004  while(p != NULL)
3005  {
3006    next = pNext(p);
3007    if (p_GetExp(p, n,r) == 0)
3008    {
3009      pNext(z) = p;
3010      pIter(z);
3011    }
3012    else
3013    {
3014      pNext(p) = n_z;
3015      n_z = p;
3016    }
3017    p = next;
3018  }
3019  pNext(z) = NULL;
3020  *zero = pNext(&sz);
3021  *non_zero = n_z;
3022}
3023/*3
3024* substitute the n-th variable by 1 in p
3025* destroy p
3026*/
3027static poly p_Subst1 (poly p,int n, const ring r)
3028{
3029  poly qq=NULL, result = NULL;
3030  poly zero=NULL, non_zero=NULL;
3031
3032  // reverse, so that add is likely to be linear
3033  p_SplitAndReversePoly(p, n, &non_zero, &zero,r);
3034
3035  while (non_zero != NULL)
3036  {
3037    assume(p_GetExp(non_zero, n,r) != 0);
3038    qq = non_zero;
3039    pIter(non_zero);
3040    qq->next = NULL;
3041    p_SetExp(qq,n,0,r);
3042    p_Setm(qq,r);
3043    result = p_Add_q(result,qq,r);
3044  }
3045  p = p_Add_q(result, zero,r);
3046  p_Test(p,r);
3047  return p;
3048}
3049
3050/*3
3051* substitute the n-th variable by number e in p
3052* destroy p
3053*/
3054static poly p_Subst2 (poly p,int n, number e, const ring r)
3055{
3056  assume( ! n_IsZero(e,r->cf) );
3057  poly qq,result = NULL;
3058  number nn, nm;
3059  poly zero, non_zero;
3060
3061  // reverse, so that add is likely to be linear
3062  p_SplitAndReversePoly(p, n, &non_zero, &zero,r);
3063
3064  while (non_zero != NULL)
3065  {
3066    assume(p_GetExp(non_zero, nm,r) != 0);
3067    qq = non_zero;
3068    pIter(non_zero);
3069    qq->next = NULL;
3070    n_Power(e, p_GetExp(qq, n, r), &nn,r->cf);
3071    nm = n_Mult(nn, pGetCoeff(qq),r->cf);
3072#ifdef HAVE_RINGS
3073    if (n_IsZero(nm,r->cf))
3074    {
3075      p_LmFree(&qq,r);
3076      n_Delete(&nm,r->cf);
3077    }
3078    else
3079#endif
3080    {
3081      p_SetCoeff(qq, nm,r);
3082      p_SetExp(qq, n, 0,r);
3083      p_Setm(qq,r);
3084      result = p_Add_q(result,qq,r);
3085    }
3086    n_Delete(&nn,r->cf);
3087  }
3088  p = p_Add_q(result, zero,r);
3089  p_Test(p,r);
3090  return p;
3091}
3092
3093
3094/* delete monoms whose n-th exponent is different from zero */
3095static poly p_Subst0(poly p, int n, const ring r)
3096{
3097  spolyrec res;
3098  poly h = &res;
3099  pNext(h) = p;
3100
3101  while (pNext(h)!=NULL)
3102  {
3103    if (p_GetExp(pNext(h),n,r)!=0)
3104    {
3105      p_LmDelete(&pNext(h),r);
3106    }
3107    else
3108    {
3109      pIter(h);
3110    }
3111  }
3112  p_Test(pNext(&res),r);
3113  return pNext(&res);
3114}
3115
3116/*2
3117* substitute the n-th variable by e in p
3118* destroy p
3119*/
3120poly p_Subst(poly p, int n, poly e, const ring r)
3121{
3122  if (e == NULL) return p_Subst0(p, n,r);
3123
3124  if (p_IsConstant(e,r))
3125  {
3126    if (n_IsOne(pGetCoeff(e),r->cf)) return p_Subst1(p,n,r);
3127    else return p_Subst2(p, n, pGetCoeff(e),r);
3128  }
3129
3130#ifdef HAVE_PLURAL
3131  if (rIsPluralRing(r))
3132  {
3133    return nc_pSubst(p,n,e,r);
3134  }
3135#endif
3136
3137  int exponent,i;
3138  poly h, res, m;
3139  int *me,*ee;
3140  number nu,nu1;
3141
3142  me=(int *)omAlloc((rVar(r)+1)*sizeof(int));
3143  ee=(int *)omAlloc((rVar(r)+1)*sizeof(int));
3144  if (e!=NULL) p_GetExpV(e,ee,r);
3145  res=NULL;
3146  h=p;
3147  while (h!=NULL)
3148  {
3149    if ((e!=NULL) || (p_GetExp(h,n,r)==0))
3150    {
3151      m=p_Head(h,r);
3152      p_GetExpV(m,me,r);
3153      exponent=me[n];
3154      me[n]=0;
3155      for(i=rVar(r);i>0;i--)
3156        me[i]+=exponent*ee[i];
3157      p_SetExpV(m,me,r);
3158      if (e!=NULL)
3159      {
3160        n_Power(pGetCoeff(e),exponent,&nu,r->cf);
3161        nu1=n_Mult(pGetCoeff(m),nu,r->cf);
3162        n_Delete(&nu,r->cf);
3163        p_SetCoeff(m,nu1,r);
3164      }
3165      res=p_Add_q(res,m,r);
3166    }
3167    p_LmDelete(&h,r);
3168  }
3169  omFreeSize((ADDRESS)me,(rVar(r)+1)*sizeof(int));
3170  omFreeSize((ADDRESS)ee,(rVar(r)+1)*sizeof(int));
3171  return res;
3172}
3173/*2
3174*returns a re-ordered copy of a polynomial, with permutation of the variables
3175*/
3176poly p_PermPoly (poly p, int * perm, const ring oldRing, const ring dst,
3177       nMapFunc nMap, int *par_perm, int OldPar)
3178{
3179  int OldpVariables = oldRing->N;
3180  poly result = NULL;
3181  poly result_last = NULL;
3182  poly aq=NULL; /* the map coefficient */
3183  poly qq; /* the mapped monomial */
3184
3185  while (p != NULL)
3186  {
3187    if ((OldPar==0)||(rField_is_GF(oldRing)))
3188    {
3189      qq = p_Init(dst);
3190      number n=nMap(pGetCoeff(p),oldRing->cf,dst->cf);
3191      if ((dst->minpoly!=NULL)
3192      && ((rField_is_Zp_a(dst)) || (rField_is_Q_a(dst))))
3193      {
3194        n_Normalize(n,dst->cf);
3195      }
3196      pGetCoeff(qq)=n;
3197    // coef may be zero:  pTest(qq);
3198    }
3199    else
3200    {
3201      qq=p_One(dst);
3202      WerrorS("longalg missing");
3203      #if 0
3204      aq=naPermNumber(pGetCoeff(p),par_perm,OldPar, oldRing);
3205      if ((dst->minpoly!=NULL)
3206      && ((rField_is_Zp_a(dst)) || (rField_is_Q_a(dst))))
3207      {
3208        poly tmp=aq;
3209        while (tmp!=NULL)
3210        {
3211          number n=pGetCoeff(tmp);
3212          n_Normalize(n,dst->cf);
3213          pGetCoeff(tmp)=n;
3214          pIter(tmp);
3215        }
3216      }
3217      p_Test(aq,dst);
3218      #endif
3219    }
3220    if (rRing_has_Comp(dst)) p_SetComp(qq, p_GetComp(p,oldRing),dst);
3221    if (n_IsZero(pGetCoeff(qq),dst->cf))
3222    {
3223      p_LmDelete(&qq,dst);
3224    }
3225    else
3226    {
3227      int i;
3228      int mapped_to_par=0;
3229      for(i=1; i<=OldpVariables; i++)
3230      {
3231        int e=p_GetExp(p,i,oldRing);
3232        if (e!=0)
3233        {
3234          if (perm==NULL)
3235          {
3236            p_SetExp(qq,i, e, dst);
3237          }
3238          else if (perm[i]>0)
3239            p_AddExp(qq,perm[i], e/*p_GetExp( p,i,oldRing)*/, dst);
3240          else if (perm[i]<0)
3241          {
3242            if (rField_is_GF(dst))
3243            {
3244              number c=pGetCoeff(qq);
3245              number ee=n_Par(1,dst->cf);
3246              number eee;n_Power(ee,e,&eee,dst->cf); //nfDelete(ee,dst);
3247              ee=n_Mult(c,eee,dst->cf);
3248              //nfDelete(c,dst);nfDelete(eee,dst);
3249              pSetCoeff0(qq,ee);
3250            }
3251            else
3252            {
3253              WerrorS("longalg missing");
3254              #if 0
3255              lnumber c=(lnumber)pGetCoeff(qq);
3256              if (c->z->next==NULL)
3257                p_AddExp(c->z,-perm[i],e/*p_GetExp( p,i,oldRing)*/,dst->algring);
3258              else /* more difficult: we have really to multiply: */
3259              {
3260                lnumber mmc=(lnumber)naInit(1,dst);
3261                p_SetExp(mmc->z,-perm[i],e/*p_GetExp( p,i,oldRing)*/,dst->algring);
3262                p_Setm(mmc->z,dst->algring->cf);
3263                pGetCoeff(qq)=n_Mult((number)c,(number)mmc,dst->cf);
3264                n_Delete((number *)&c,dst->cf);
3265                n_Delete((number *)&mmc,dst->cf);
3266              }
3267              mapped_to_par=1;
3268              #endif
3269            }
3270          }
3271          else
3272          {
3273            /* this variable maps to 0 !*/
3274            p_LmDelete(&qq,dst);
3275            break;
3276          }
3277        }
3278      }
3279      if (mapped_to_par
3280      && (dst->minpoly!=NULL))
3281      {
3282        number n=pGetCoeff(qq);
3283        n_Normalize(n,dst->cf);
3284        pGetCoeff(qq)=n;
3285      }
3286    }
3287    pIter(p);
3288#if 1
3289    if (qq!=NULL)
3290    {
3291      p_Setm(qq,dst);
3292      p_Test(aq,dst);
3293      p_Test(qq,dst);
3294      if (aq!=NULL) qq=p_Mult_q(aq,qq,dst);
3295      aq = qq;
3296      while (pNext(aq) != NULL) pIter(aq);
3297      if (result_last==NULL)
3298      {
3299        result=qq;
3300      }
3301      else
3302      {
3303        pNext(result_last)=qq;
3304      }
3305      result_last=aq;
3306      aq = NULL;
3307    }
3308    else if (aq!=NULL)
3309    {
3310      p_Delete(&aq,dst);
3311    }
3312  }
3313  result=p_SortAdd(result,dst);
3314#else
3315  //  if (qq!=NULL)
3316  //  {
3317  //    pSetm(qq);
3318  //    pTest(qq);
3319  //    pTest(aq);
3320  //    if (aq!=NULL) qq=pMult(aq,qq);
3321  //    aq = qq;
3322  //    while (pNext(aq) != NULL) pIter(aq);
3323  //    pNext(aq) = result;
3324  //    aq = NULL;
3325  //    result = qq;
3326  //  }
3327  //  else if (aq!=NULL)
3328  //  {
3329  //    pDelete(&aq);
3330  //  }
3331  //}
3332  //p = result;
3333  //result = NULL;
3334  //while (p != NULL)
3335  //{
3336  //  qq = p;
3337  //  pIter(p);
3338  //  qq->next = NULL;
3339  //  result = pAdd(result, qq);
3340  //}
3341#endif
3342  p_Test(result,dst);
3343  return result;
3344}
3345/**************************************************************
3346 *
3347 * Jet
3348 *
3349 **************************************************************/
3350
3351poly pp_Jet(poly p, int m, const ring R)
3352{
3353  poly r=NULL;
3354  poly t=NULL;
3355
3356  while (p!=NULL)
3357  {
3358    if (p_Totaldegree(p,R)<=m)
3359    {
3360      if (r==NULL)
3361        r=p_Head(p,R);
3362      else
3363      if (t==NULL)
3364      {
3365        pNext(r)=p_Head(p,R);
3366        t=pNext(r);
3367      }
3368      else
3369      {
3370        pNext(t)=p_Head(p,R);
3371        pIter(t);
3372      }
3373    }
3374    pIter(p);
3375  }
3376  return r;
3377}
3378
3379poly p_Jet(poly p, int m,const ring R)
3380{
3381  poly t=NULL;
3382
3383  while((p!=NULL) && (p_Totaldegree(p,R)>m)) p_LmDelete(&p,R);
3384  if (p==NULL) return NULL;
3385  poly r=p;
3386  while (pNext(p)!=NULL)
3387  {
3388    if (p_Totaldegree(pNext(p),R)>m)
3389    {
3390      p_LmDelete(&pNext(p),R);
3391    }
3392    else
3393      pIter(p);
3394  }
3395  return r;
3396}
3397
3398poly pp_JetW(poly p, int m, short *w, const ring R)
3399{
3400  poly r=NULL;
3401  poly t=NULL;
3402  while (p!=NULL)
3403  {
3404    if (totaldegreeWecart_IV(p,R,w)<=m)
3405    {
3406      if (r==NULL)
3407        r=p_Head(p,R);
3408      else
3409      if (t==NULL)
3410      {
3411        pNext(r)=p_Head(p,R);
3412        t=pNext(r);
3413      }
3414      else
3415      {
3416        pNext(t)=p_Head(p,R);
3417        pIter(t);
3418      }
3419    }
3420    pIter(p);
3421  }
3422  return r;
3423}
3424
3425poly p_JetW(poly p, int m, short *w, const ring R)
3426{
3427  poly t=NULL;
3428  while((p!=NULL) && (totaldegreeWecart_IV(p,R,w)>m)) p_LmDelete(&p,R);
3429  if (p==NULL) return NULL;
3430  poly r=p;
3431  while (pNext(p)!=NULL)
3432  {
3433    if (totaldegreeWecart_IV(pNext(p),R,w)>m)
3434    {
3435      p_LmDelete(&pNext(p),R);
3436    }
3437    else
3438      pIter(p);
3439  }
3440  return r;
3441}
3442
3443/*************************************************************/
3444int p_MinDeg(poly p,intvec *w, const ring R)
3445{
3446  if(p==NULL)
3447    return -1;
3448  int d=-1;
3449  while(p!=NULL)
3450  {
3451    int d0=0;
3452    for(int j=0;j<rVar(R);j++)
3453      if(w==NULL||j>=w->length())
3454        d0+=p_GetExp(p,j+1,R);
3455      else
3456        d0+=(*w)[j]*p_GetExp(p,j+1,R);
3457    if(d0<d||d==-1)
3458      d=d0;
3459    pIter(p);
3460  }
3461  return d;
3462}
3463
3464/***************************************************************
3465 *
3466 * p_ShallowDelete
3467 *
3468 ***************************************************************/
3469#undef LINKAGE
3470#define LINKAGE
3471#undef p_Delete__T
3472#define p_Delete__T p_ShallowDelete
3473#undef n_Delete__T
3474#define n_Delete__T(n, r) ((void)0)
3475
3476#include <polys/templates/p_Delete__T.cc>
3477
3478#ifdef HAVE_RINGS
3479/* TRUE iff LT(f) | LT(g) */
3480BOOLEAN p_DivisibleByRingCase(poly f, poly g, const ring r)
3481{
3482  int exponent;
3483  for(int i = (int)r->N; i; i--)
3484  {
3485    exponent = p_GetExp(g, i, r) - p_GetExp(f, i, r);
3486    if (exponent < 0) return FALSE;
3487  }
3488  return n_DivBy(p_GetCoeff(g,r), p_GetCoeff(f,r),r->cf);
3489}
3490#endif
Note: See TracBrowser for help on using the repository browser.