source: git/libpolys/polys/monomials/p_polys.cc @ 38500a

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