source: git/libpolys/polys/monomials/p_polys.cc @ 71ba5b8

spielwiese
Last change on this file since 71ba5b8 was 71ba5b8, checked in by Hans Schoenemann <hannes@…>, 12 years ago
removed polys.cc
  • Property mode set to 100644
File size: 69.4 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 <misc/intvec.h>
22// #include <???/ideals.h>
23// #include <???/int64vec.h>
24#ifndef NDEBUG
25// #include <???/febase.h>
26#endif
27
28/***************************************************************
29 *
30 * Completing what needs to be set for the monomial
31 *
32 ***************************************************************/
33// this is special for the syz stuff
34static int* _components = NULL;
35static long* _componentsShifted = NULL;
36static int _componentsExternal = 0;
37
38BOOLEAN pSetm_error=0;
39
40#ifndef NDEBUG
41# define MYTEST 0
42#else /* ifndef NDEBUG */
43# define MYTEST 0
44#endif /* ifndef NDEBUG */
45
46void p_Setm_General(poly p, const ring r)
47{
48  p_LmCheckPolyRing(p, r);
49  int pos=0;
50  if (r->typ!=NULL)
51  {
52    loop
53    {
54      long ord=0;
55      sro_ord* o=&(r->typ[pos]);
56      switch(o->ord_typ)
57      {
58        case ro_dp:
59        {
60          int a,e;
61          a=o->data.dp.start;
62          e=o->data.dp.end;
63          for(int i=a;i<=e;i++) ord+=p_GetExp(p,i,r);
64          p->exp[o->data.dp.place]=ord;
65          break;
66        }
67        case ro_wp_neg:
68          ord=POLY_NEGWEIGHT_OFFSET;
69          // no break;
70        case ro_wp:
71        {
72          int a,e;
73          a=o->data.wp.start;
74          e=o->data.wp.end;
75          int *w=o->data.wp.weights;
76#if 1
77          for(int i=a;i<=e;i++) ord+=p_GetExp(p,i,r)*w[i-a];
78#else
79          long ai;
80          int ei,wi;
81          for(int i=a;i<=e;i++)
82          {
83             ei=p_GetExp(p,i,r);
84             wi=w[i-a];
85             ai=ei*wi;
86             if (ai/ei!=wi) pSetm_error=TRUE;
87             ord+=ai;
88             if (ord<ai) pSetm_error=TRUE;
89          }
90#endif
91          p->exp[o->data.wp.place]=ord;
92          break;
93        }
94      case ro_wp64:
95        {
96          int64 ord=0;
97          int a,e;
98          a=o->data.wp64.start;
99          e=o->data.wp64.end;
100          int64 *w=o->data.wp64.weights64;
101          int64 ei,wi,ai;
102          for(int i=a;i<=e;i++)
103          {
104            //Print("exp %d w %d \n",p_GetExp(p,i,r),(int)w[i-a]);
105            //ord+=((int64)p_GetExp(p,i,r))*w[i-a];
106            ei=(int64)p_GetExp(p,i,r);
107            wi=w[i-a];
108            ai=ei*wi;
109            if(ei!=0 && ai/ei!=wi)
110            {
111              pSetm_error=TRUE;
112              #if SIZEOF_LONG == 4
113              Print("ai %lld, wi %lld\n",ai,wi);
114              #else
115              Print("ai %ld, wi %ld\n",ai,wi);
116              #endif
117            }
118            ord+=ai;
119            if (ord<ai)
120            {
121              pSetm_error=TRUE;
122              #if SIZEOF_LONG == 4
123              Print("ai %lld, ord %lld\n",ai,ord);
124              #else
125              Print("ai %ld, ord %ld\n",ai,ord);
126              #endif
127            }
128          }
129          int64 mask=(int64)0x7fffffff;
130          long a_0=(long)(ord&mask); //2^31
131          long a_1=(long)(ord >>31 ); /*(ord/(mask+1));*/
132
133          //Print("mask: %x,  ord: %d,  a_0: %d,  a_1: %d\n"
134          //,(int)mask,(int)ord,(int)a_0,(int)a_1);
135                    //Print("mask: %d",mask);
136
137          p->exp[o->data.wp64.place]=a_1;
138          p->exp[o->data.wp64.place+1]=a_0;
139//            if(p_Setm_error) Print("***************************\n
140//                                    ***************************\n
141//                                    **WARNING: overflow error**\n
142//                                    ***************************\n
143//                                    ***************************\n");
144          break;
145        }
146        case ro_cp:
147        {
148          int a,e;
149          a=o->data.cp.start;
150          e=o->data.cp.end;
151          int pl=o->data.cp.place;
152          for(int i=a;i<=e;i++) { p->exp[pl]=p_GetExp(p,i,r); pl++; }
153          break;
154        }
155        case ro_syzcomp:
156        {
157          int c=p_GetComp(p,r);
158          long sc = c;
159          int* Components = (_componentsExternal ? _components :
160                             o->data.syzcomp.Components);
161          long* ShiftedComponents = (_componentsExternal ? _componentsShifted:
162                                     o->data.syzcomp.ShiftedComponents);
163          if (ShiftedComponents != NULL)
164          {
165            assume(Components != NULL);
166            assume(c == 0 || Components[c] != 0);
167            sc = ShiftedComponents[Components[c]];
168            assume(c == 0 || sc != 0);
169          }
170          p->exp[o->data.syzcomp.place]=sc;
171          break;
172        }
173        case ro_syz:
174        {
175          const unsigned long c = p_GetComp(p, r);
176          const short place = o->data.syz.place;
177          const int limit = o->data.syz.limit;
178         
179          if (c > limit)
180            p->exp[place] = o->data.syz.curr_index;
181          else if (c > 0)
182          {
183            assume( (1 <= c) && (c <= limit) );
184            p->exp[place]= o->data.syz.syz_index[c];
185          }
186          else
187          {
188            assume(c == 0);
189            p->exp[place]= 0;
190          }
191          break;
192        }
193        // Prefix for Induced Schreyer ordering
194        case ro_isTemp: // Do nothing?? (to be removed into suffix later on...?)
195        {
196          assume(p != NULL);
197
198#ifndef NDEBUG
199#if MYTEST
200          Print("p_Setm_General: isTemp ord: pos: %d, p: ", pos);  p_DebugPrint(p, r, r, 1);
201#endif
202#endif
203          int c = p_GetComp(p, r);
204
205          assume( c >= 0 );
206
207          // Let's simulate case ro_syz above....
208          // Should accumulate (by Suffix) and be a level indicator
209          const int* const pVarOffset = o->data.isTemp.pVarOffset;
210
211          assume( pVarOffset != NULL );
212
213          // TODO: Can this be done in the suffix???
214          for( int i = 1; i <= r->N; i++ ) // No v[0] here!!!
215          {
216            const int vo = pVarOffset[i];
217            if( vo != -1) // TODO: optimize: can be done once!
218            {
219              // Hans! Please don't break it again! p_SetExp(p, ..., r, vo) is correct:
220              p_SetExp(p, p_GetExp(p, i, r), r, vo); // copy put them verbatim
221              // Hans! Please don't break it again! p_GetExp(p, r, vo) is correct:
222              assume( p_GetExp(p, r, vo) == p_GetExp(p, i, r) ); // copy put them verbatim
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      Werror("longalg missing");
1874      #if 0
1875      while (p!=NULL)
1876      { // each monom: coeff in Q_a
1877        lnumber c_n_n=(lnumber)pGetCoeff(p);
1878        poly c_n=c_n_n->z;
1879        while (c_n!=NULL)
1880        { // each monom: coeff in Q
1881          d=nlLcm(hzz,pGetCoeff(c_n),r->algring->cf);
1882          n_Delete(&hzz,r->algring->cf);
1883          hzz=d;
1884          pIter(c_n);
1885        }
1886        c_n=c_n_n->n;
1887        while (c_n!=NULL)
1888        { // each monom: coeff in Q
1889          d=nlLcm(h,pGetCoeff(c_n),r->algring->cf);
1890          n_Delete(&h,r->algring->cf);
1891          h=d;
1892          pIter(c_n);
1893        }
1894        pIter(p);
1895      }
1896      /* hzz contains the 1/lcm of all denominators in c_n_n->z*/
1897      /* h contains the 1/lcm of all denominators in c_n_n->n*/
1898      number htmp=nlInvers(h,r->algring->cf);
1899      number hzztmp=nlInvers(hzz,r->algring->cf);
1900      number hh=nlMult(hzz,h,r->algring->cf);
1901      nlDelete(&hzz,r->algring->cf);
1902      nlDelete(&h,r->algring->cf);
1903      number hg=nlGcd(hzztmp,htmp,r->algring->cf);
1904      nlDelete(&hzztmp,r->algring->cf);
1905      nlDelete(&htmp,r->algring->cf);
1906      h=nlMult(hh,hg,r->algring->cf);
1907      nlDelete(&hg,r->algring->cf);
1908      nlDelete(&hh,r->algring->cf);
1909      nlNormalize(h,r->algring->cf);
1910      if(!nlIsOne(h,r->algring->cf))
1911      {
1912        p=ph;
1913        while (p!=NULL)
1914        { // each monom: coeff in Q_a
1915          lnumber c_n_n=(lnumber)pGetCoeff(p);
1916          poly c_n=c_n_n->z;
1917          while (c_n!=NULL)
1918          { // each monom: coeff in Q
1919            d=nlMult(h,pGetCoeff(c_n),r->algring->cf);
1920            nlNormalize(d,r->algring->cf);
1921            nlDelete(&pGetCoeff(c_n),r->algring->cf);
1922            pGetCoeff(c_n)=d;
1923            pIter(c_n);
1924          }
1925          c_n=c_n_n->n;
1926          while (c_n!=NULL)
1927          { // each monom: coeff in Q
1928            d=nlMult(h,pGetCoeff(c_n),r->algring->cf);
1929            nlNormalize(d,r->algring->cf);
1930            nlDelete(&pGetCoeff(c_n),r->algring->cf);
1931            pGetCoeff(c_n)=d;
1932            pIter(c_n);
1933          }
1934          pIter(p);
1935        }
1936      }
1937      nlDelete(&h,r->algring->cf);
1938      #endif
1939    }
1940  }
1941}
1942#if 0 // currently not used
1943void p_SimpleContent(poly ph,int smax, const ring r)
1944{
1945  if(TEST_OPT_CONTENTSB) return;
1946  if (ph==NULL) return;
1947  if (pNext(ph)==NULL)
1948  {
1949    p_SetCoeff(ph,n_Init(1,r_cf),r);
1950    return;
1951  }
1952  if ((pNext(pNext(ph))==NULL)||(!rField_is_Q(r)))
1953  {
1954    return;
1955  }
1956  number d=p_InitContent(ph,r);
1957  if (nlSize(d,r->cf)<=smax)
1958  {
1959    //if (TEST_OPT_PROT) PrintS("G");
1960    return;
1961  }
1962  poly p=ph;
1963  number h=d;
1964  if (smax==1) smax=2;
1965  while (p!=NULL)
1966  {
1967#if 0
1968    d=nlGcd(h,pGetCoeff(p),r->cf);
1969    nlDelete(&h,r->cf);
1970    h = d;
1971#else
1972    nlInpGcd(h,pGetCoeff(p),r->cf);
1973#endif
1974    if(nlSize(h,r->cf)<smax)
1975    {
1976      //if (TEST_OPT_PROT) PrintS("g");
1977      return;
1978    }
1979    pIter(p);
1980  }
1981  p = ph;
1982  if (!nlGreaterZero(pGetCoeff(p),r->cf)) h=nlNeg(h,r->cf);
1983  if(nlIsOne(h,r->cf)) return;
1984  //if (TEST_OPT_PROT) PrintS("c");
1985  while (p!=NULL)
1986  {
1987#if 1
1988    d = nlIntDiv(pGetCoeff(p),h,r->cf);
1989    p_SetCoeff(p,d,r);
1990#else
1991    nlInpIntDiv(pGetCoeff(p),h,r->cf);
1992#endif
1993    pIter(p);
1994  }
1995  nlDelete(&h,r->cf);
1996}
1997#endif
1998
1999static number p_InitContent(poly ph, const ring r)
2000// only for coefficients in Q
2001#if 0
2002{
2003  assume(!TEST_OPT_CONTENTSB);
2004  assume(ph!=NULL);
2005  assume(pNext(ph)!=NULL);
2006  assume(rField_is_Q(r));
2007  if (pNext(pNext(ph))==NULL)
2008  {
2009    return nlGetNom(pGetCoeff(pNext(ph)),r->cf);
2010  }
2011  poly p=ph;
2012  number n1=nlGetNom(pGetCoeff(p),r->cf);
2013  pIter(p);
2014  number n2=nlGetNom(pGetCoeff(p),r->cf);
2015  pIter(p);
2016  number d;
2017  number t;
2018  loop
2019  {
2020    nlNormalize(pGetCoeff(p),r->cf);
2021    t=nlGetNom(pGetCoeff(p),r->cf);
2022    if (nlGreaterZero(t,r->cf))
2023      d=nlAdd(n1,t,r->cf);
2024    else
2025      d=nlSub(n1,t,r->cf);
2026    nlDelete(&t,r->cf);
2027    nlDelete(&n1,r->cf);
2028    n1=d;
2029    pIter(p);
2030    if (p==NULL) break;
2031    nlNormalize(pGetCoeff(p),r->cf);
2032    t=nlGetNom(pGetCoeff(p),r->cf);
2033    if (nlGreaterZero(t,r->cf))
2034      d=nlAdd(n2,t,r->cf);
2035    else
2036      d=nlSub(n2,t,r->cf);
2037    nlDelete(&t,r->cf);
2038    nlDelete(&n2,r->cf);
2039    n2=d;
2040    pIter(p);
2041    if (p==NULL) break;
2042  }
2043  d=nlGcd(n1,n2,r->cf);
2044  nlDelete(&n1,r->cf);
2045  nlDelete(&n2,r->cf);
2046  return d;
2047}
2048#else
2049{
2050  number d=pGetCoeff(ph);
2051  if(SR_HDL(d)&SR_INT) return d;
2052  int s=mpz_size1(d->z);
2053  int s2=-1;
2054  number d2;
2055  loop
2056  {
2057    pIter(ph);
2058    if(ph==NULL)
2059    {
2060      if (s2==-1) return nlCopy(d,r->cf);
2061      break;
2062    }
2063    if (SR_HDL(pGetCoeff(ph))&SR_INT)
2064    {
2065      s2=s;
2066      d2=d;
2067      s=0;
2068      d=pGetCoeff(ph);
2069      if (s2==0) break;
2070    }
2071    else
2072    if (mpz_size1((pGetCoeff(ph)->z))<=s)
2073    {
2074      s2=s;
2075      d2=d;
2076      d=pGetCoeff(ph);
2077      s=mpz_size1(d->z);
2078    }
2079  }
2080  return nlGcd(d,d2,r->cf);
2081}
2082#endif
2083
2084number p_InitContent_a(poly ph, const ring r)
2085// only for coefficients in K(a) anf K(a,...)
2086{
2087  number d=pGetCoeff(ph);
2088  int s=n_ParDeg(d,r->cf);
2089  if (s /* n_ParDeg(d)*/ <=1) return n_Copy(d,r->cf);
2090  int s2=-1;
2091  number d2;
2092  int ss;
2093  loop
2094  {
2095    pIter(ph);
2096    if(ph==NULL)
2097    {
2098      if (s2==-1) return n_Copy(d,r->cf);
2099      break;
2100    }
2101    if ((ss=n_ParDeg(pGetCoeff(ph),r->cf))<s)
2102    {
2103      s2=s;
2104      d2=d;
2105      s=ss;
2106      d=pGetCoeff(ph);
2107      if (s2<=1) break;
2108    }
2109  }
2110  return n_Gcd(d,d2,r->cf);
2111}
2112
2113
2114//void pContent(poly ph)
2115//{
2116//  number h,d;
2117//  poly p;
2118//
2119//  p = ph;
2120//  if(pNext(p)==NULL)
2121//  {
2122//    pSetCoeff(p,nInit(1));
2123//  }
2124//  else
2125//  {
2126//#ifdef PDEBUG
2127//    if (!pTest(p)) return;
2128//#endif
2129//    nNormalize(pGetCoeff(p));
2130//    if(!nGreaterZero(pGetCoeff(ph)))
2131//    {
2132//      ph = pNeg(ph);
2133//      nNormalize(pGetCoeff(p));
2134//    }
2135//    h=pGetCoeff(p);
2136//    pIter(p);
2137//    while (p!=NULL)
2138//    {
2139//      nNormalize(pGetCoeff(p));
2140//      if (nGreater(h,pGetCoeff(p))) h=pGetCoeff(p);
2141//      pIter(p);
2142//    }
2143//    h=nCopy(h);
2144//    p=ph;
2145//    while (p!=NULL)
2146//    {
2147//      d=nGcd(h,pGetCoeff(p));
2148//      nDelete(&h);
2149//      h = d;
2150//      if(nIsOne(h))
2151//      {
2152//        break;
2153//      }
2154//      pIter(p);
2155//    }
2156//    p = ph;
2157//    //number tmp;
2158//    if(!nIsOne(h))
2159//    {
2160//      while (p!=NULL)
2161//      {
2162//        d = nIntDiv(pGetCoeff(p),h);
2163//        pSetCoeff(p,d);
2164//        pIter(p);
2165//      }
2166//    }
2167//    nDelete(&h);
2168//#ifdef HAVE_FACTORY
2169//    if ( (nGetChar() == 1) || (nGetChar() < 0) ) /* Q[a],Q(a),Zp[a],Z/p(a) */
2170//    {
2171//      pTest(ph);
2172//      singclap_divide_content(ph);
2173//      pTest(ph);
2174//    }
2175//#endif
2176//  }
2177//}
2178#if 0
2179void p_Content(poly ph, const ring r)
2180{
2181  number h,d;
2182  poly p;
2183
2184  if(pNext(ph)==NULL)
2185  {
2186    p_SetCoeff(ph,n_Init(1,r->cf),r);
2187  }
2188  else
2189  {
2190    n_Normalize(pGetCoeff(ph),r->cf);
2191    if(!n_GreaterZero(pGetCoeff(ph),r->cf)) ph = p_Neg(ph,r);
2192    h=n_Copy(pGetCoeff(ph),r->cf);
2193    p = pNext(ph);
2194    while (p!=NULL)
2195    {
2196      n_Normalize(pGetCoeff(p),r->cf);
2197      d=n_Gcd(h,pGetCoeff(p),r->cf);
2198      n_Delete(&h,r->cf);
2199      h = d;
2200      if(n_IsOne(h,r->cf))
2201      {
2202        break;
2203      }
2204      pIter(p);
2205    }
2206    p = ph;
2207    //number tmp;
2208    if(!n_IsOne(h,r->cf))
2209    {
2210      while (p!=NULL)
2211      {
2212        //d = nDiv(pGetCoeff(p),h);
2213        //tmp = nIntDiv(pGetCoeff(p),h);
2214        //if (!nEqual(d,tmp))
2215        //{
2216        //  StringSetS("** div0:");nWrite(pGetCoeff(p));StringAppendS("/");
2217        //  nWrite(h);StringAppendS("=");nWrite(d);StringAppendS(" int:");
2218        //  nWrite(tmp);Print(StringAppendS("\n"));
2219        //}
2220        //nDelete(&tmp);
2221        d = n_IntDiv(pGetCoeff(p),h,r->cf);
2222        p_SetCoeff(p,d,r->cf);
2223        pIter(p);
2224      }
2225    }
2226    n_Delete(&h,r->cf);
2227#ifdef HAVE_FACTORY
2228    //if ( (n_GetChar(r) == 1) || (n_GetChar(r) < 0) ) /* Q[a],Q(a),Zp[a],Z/p(a) */
2229    //{
2230    //  singclap_divide_content(ph);
2231    //  if(!n_GreaterZero(pGetCoeff(ph),r)) ph = p_Neg(ph,r);
2232    //}
2233#endif
2234  }
2235}
2236#endif
2237/* ---------------------------------------------------------------------------*/
2238/* cleardenom suff                                                           */
2239poly p_Cleardenom(poly ph, const ring r)
2240{
2241  poly start=ph;
2242  number d, h;
2243  poly p;
2244
2245#ifdef HAVE_RINGS
2246  if (rField_is_Ring(r))
2247  {
2248    p_Content(ph,r);
2249    return start;
2250  }
2251#endif
2252  if (rField_is_Zp(r) && TEST_OPT_INTSTRATEGY) return start;
2253  p = ph;
2254  if(pNext(p)==NULL)
2255  {
2256    if (TEST_OPT_CONTENTSB)
2257    {
2258      number n=n_GetDenom(pGetCoeff(p),r->cf);
2259      if (!n_IsOne(n,r->cf))
2260      {
2261        number nn=n_Mult(pGetCoeff(p),n,r->cf);
2262        n_Normalize(nn,r->cf);
2263        p_SetCoeff(p,nn,r);
2264      }
2265      n_Delete(&n,r->cf);
2266    }
2267    else
2268      p_SetCoeff(p,n_Init(1,r->cf),r);
2269  }
2270  else
2271  {
2272    h = n_Init(1,r->cf);
2273    while (p!=NULL)
2274    {
2275      n_Normalize(pGetCoeff(p),r->cf);
2276      d=n_Lcm(h,pGetCoeff(p),r->cf);
2277      n_Delete(&h,r->cf);
2278      h=d;
2279      pIter(p);
2280    }
2281    /* contains the 1/lcm of all denominators */
2282    if(!n_IsOne(h,r->cf))
2283    {
2284      p = ph;
2285      while (p!=NULL)
2286      {
2287        /* should be:
2288        * number hh;
2289        * nGetDenom(p->coef,&hh);
2290        * nMult(&h,&hh,&d);
2291        * nNormalize(d);
2292        * nDelete(&hh);
2293        * nMult(d,p->coef,&hh);
2294        * nDelete(&d);
2295        * nDelete(&(p->coef));
2296        * p->coef =hh;
2297        */
2298        d=n_Mult(h,pGetCoeff(p),r->cf);
2299        n_Normalize(d,r->cf);
2300        p_SetCoeff(p,d,r);
2301        pIter(p);
2302      }
2303      n_Delete(&h,r->cf);
2304      if (n_GetChar(r->cf)==1)
2305      {
2306        loop
2307        {
2308          h = n_Init(1,r->cf);
2309          p=ph;
2310          while (p!=NULL)
2311          {
2312            d=n_Lcm(h,pGetCoeff(p),r->cf);
2313            n_Delete(&h,r->cf);
2314            h=d;
2315            pIter(p);
2316          }
2317          /* contains the 1/lcm of all denominators */
2318          if(!n_IsOne(h,r->cf))
2319          {
2320            p = ph;
2321            while (p!=NULL)
2322            {
2323              /* should be:
2324              * number hh;
2325              * nGetDenom(p->coef,&hh);
2326              * nMult(&h,&hh,&d);
2327              * nNormalize(d);
2328              * nDelete(&hh);
2329              * nMult(d,p->coef,&hh);
2330              * nDelete(&d);
2331              * nDelete(&(p->coef));
2332              * p->coef =hh;
2333              */
2334              d=n_Mult(h,pGetCoeff(p),r->cf);
2335              n_Normalize(d,r->cf);
2336              p_SetCoeff(p,d,r);
2337              pIter(p);
2338            }
2339            n_Delete(&h,r->cf);
2340          }
2341          else
2342          {
2343            n_Delete(&h,r->cf);
2344            break;
2345          }
2346        }
2347      }
2348    }
2349    if (h!=NULL) n_Delete(&h,r->cf);
2350
2351    p_Content(ph,r);
2352#ifdef HAVE_RATGRING
2353    if (rIsRatGRing(r))
2354    {
2355      /* quick unit detection in the rational case is done in gr_nc_bba */
2356      pContentRat(ph);
2357      start=ph;
2358    }
2359#endif
2360  }
2361  return start;
2362}
2363
2364void p_Cleardenom_n(poly ph,const ring r,number &c)
2365{
2366  number d, h;
2367  poly p;
2368
2369  p = ph;
2370  if(pNext(p)==NULL)
2371  {
2372    c=n_Invers(pGetCoeff(p),r->cf);
2373    p_SetCoeff(p,n_Init(1,r->cf),r);
2374  }
2375  else
2376  {
2377    h = n_Init(1,r->cf);
2378    while (p!=NULL)
2379    {
2380      n_Normalize(pGetCoeff(p),r->cf);
2381      d=n_Lcm(h,pGetCoeff(p),r->cf);
2382      n_Delete(&h,r->cf);
2383      h=d;
2384      pIter(p);
2385    }
2386    c=h;
2387    /* contains the 1/lcm of all denominators */
2388    if(!n_IsOne(h,r->cf))
2389    {
2390      p = ph;
2391      while (p!=NULL)
2392      {
2393        /* should be:
2394        * number hh;
2395        * nGetDenom(p->coef,&hh);
2396        * nMult(&h,&hh,&d);
2397        * nNormalize(d);
2398        * nDelete(&hh);
2399        * nMult(d,p->coef,&hh);
2400        * nDelete(&d);
2401        * nDelete(&(p->coef));
2402        * p->coef =hh;
2403        */
2404        d=n_Mult(h,pGetCoeff(p),r->cf);
2405        n_Normalize(d,r->cf);
2406        p_SetCoeff(p,d,r);
2407        pIter(p);
2408      }
2409      if (rField_is_Q_a(r))
2410      {
2411        loop
2412        {
2413          h = n_Init(1,r->cf);
2414          p=ph;
2415          while (p!=NULL)
2416          {
2417            d=n_Lcm(h,pGetCoeff(p),r->cf);
2418            n_Delete(&h,r->cf);
2419            h=d;
2420            pIter(p);
2421          }
2422          /* contains the 1/lcm of all denominators */
2423          if(!n_IsOne(h,r->cf))
2424          {
2425            p = ph;
2426            while (p!=NULL)
2427            {
2428              /* should be:
2429              * number hh;
2430              * nGetDenom(p->coef,&hh);
2431              * nMult(&h,&hh,&d);
2432              * nNormalize(d);
2433              * nDelete(&hh);
2434              * nMult(d,p->coef,&hh);
2435              * nDelete(&d);
2436              * nDelete(&(p->coef));
2437              * p->coef =hh;
2438              */
2439              d=n_Mult(h,pGetCoeff(p),r->cf);
2440              n_Normalize(d,r->cf);
2441              p_SetCoeff(p,d,r);
2442              pIter(p);
2443            }
2444            number t=n_Mult(c,h,r->cf);
2445            n_Delete(&c,r->cf);
2446            c=t;
2447          }
2448          else
2449          {
2450            break;
2451          }
2452          n_Delete(&h,r->cf);
2453        }
2454      }
2455    }
2456  }
2457}
2458
2459number p_GetAllDenom(poly ph, const ring r)
2460{
2461  number d=n_Init(1,r->cf);
2462  poly p = ph;
2463
2464  while (p!=NULL)
2465  {
2466    number h=n_GetDenom(pGetCoeff(p),r->cf);
2467    if (!n_IsOne(h,r->cf))
2468    {
2469      number dd=n_Mult(d,h,r->cf);
2470      n_Delete(&d,r->cf);
2471      d=dd;
2472    }
2473    n_Delete(&h,r->cf);
2474    pIter(p);
2475  }
2476  return d;
2477}
2478
2479int p_Size(poly p, const ring r)
2480{
2481  int count = 0;
2482  while ( p != NULL )
2483  {
2484    count+= n_Size( pGetCoeff( p ), r->cf );
2485    pIter( p );
2486  }
2487  return count;
2488}
2489
2490/*2
2491*make p homogeneous by multiplying the monomials by powers of x_varnum
2492*assume: deg(var(varnum))==1
2493*/
2494poly p_Homogen (poly p, int varnum, const ring r)
2495{
2496  pFDegProc deg;
2497  if (r->pLexOrder && (r->order[0]==ringorder_lp))
2498    deg=p_Totaldegree;
2499  else
2500    deg=pFDeg;
2501
2502  poly q=NULL, qn;
2503  int  o,ii;
2504  sBucket_pt bp;
2505
2506  if (p!=NULL)
2507  {
2508    if ((varnum < 1) || (varnum > rVar(r)))
2509    {
2510      return NULL;
2511    }
2512    o=deg(p,r);
2513    q=pNext(p);
2514    while (q != NULL)
2515    {
2516      ii=deg(q,r);
2517      if (ii>o) o=ii;
2518      pIter(q);
2519    }
2520    q = p_Copy(p,r);
2521    bp = sBucketCreate(r);
2522    while (q != NULL)
2523    {
2524      ii = o-deg(q,r);
2525      if (ii!=0)
2526      {
2527        p_AddExp(q,varnum, (long)ii,r);
2528        p_Setm(q,r);
2529      }
2530      qn = pNext(q);
2531      pNext(q) = NULL;
2532      sBucket_Add_p(bp, q, 1);
2533      q = qn;
2534    }
2535    sBucketDestroyAdd(bp, &q, &ii);
2536  }
2537  return q;
2538}
2539
2540/*2
2541*tests if p is homogeneous with respect to the actual weigths
2542*/
2543BOOLEAN p_IsHomogeneous (poly p, const ring r)
2544{
2545  poly qp=p;
2546  int o;
2547
2548  if ((p == NULL) || (pNext(p) == NULL)) return TRUE;
2549  pFDegProc d;
2550  if (r->pLexOrder && (r->order[0]==ringorder_lp))
2551    d=p_Totaldegree;
2552  else
2553    d=pFDeg;
2554  o = d(p,r);
2555  do
2556  {
2557    if (d(qp,r) != o) return FALSE;
2558    pIter(qp);
2559  }
2560  while (qp != NULL);
2561  return TRUE;
2562}
2563
2564/*----------utilities for syzygies--------------*/
2565BOOLEAN   p_VectorHasUnitB(poly p, int * k, const ring r)
2566{
2567  poly q=p,qq;
2568  int i;
2569
2570  while (q!=NULL)
2571  {
2572    if (p_LmIsConstantComp(q,r))
2573    {
2574      i = p_GetComp(q,r);
2575      qq = p;
2576      while ((qq != q) && (p_GetComp(qq,r) != i)) pIter(qq);
2577      if (qq == q)
2578      {
2579        *k = i;
2580        return TRUE;
2581      }
2582      else
2583        pIter(q);
2584    }
2585    else pIter(q);
2586  }
2587  return FALSE;
2588}
2589
2590void   p_VectorHasUnit(poly p, int * k, int * len, const ring r)
2591{
2592  poly q=p,qq;
2593  int i,j=0;
2594
2595  *len = 0;
2596  while (q!=NULL)
2597  {
2598    if (p_LmIsConstantComp(q,r))
2599    {
2600      i = p_GetComp(q,r);
2601      qq = p;
2602      while ((qq != q) && (p_GetComp(qq,r) != i)) pIter(qq);
2603      if (qq == q)
2604      {
2605       j = 0;
2606       while (qq!=NULL)
2607       {
2608         if (p_GetComp(qq,r)==i) j++;
2609        pIter(qq);
2610       }
2611       if ((*len == 0) || (j<*len))
2612       {
2613         *len = j;
2614         *k = i;
2615       }
2616      }
2617    }
2618    pIter(q);
2619  }
2620}
2621
2622poly p_TakeOutComp1(poly * p, int k, const ring r)
2623{
2624  poly q = *p;
2625
2626  if (q==NULL) return NULL;
2627
2628  poly qq=NULL,result = NULL;
2629
2630  if (p_GetComp(q,r)==k)
2631  {
2632    result = q; /* *p */
2633    while ((q!=NULL) && (p_GetComp(q,r)==k))
2634    {
2635      p_SetComp(q,0,r);
2636      p_SetmComp(q,r);
2637      qq = q;
2638      pIter(q);
2639    }
2640    *p = q;
2641    pNext(qq) = NULL;
2642  }
2643  if (q==NULL) return result;
2644//  if (pGetComp(q) > k) pGetComp(q)--;
2645  while (pNext(q)!=NULL)
2646  {
2647    if (p_GetComp(pNext(q),r)==k)
2648    {
2649      if (result==NULL)
2650      {
2651        result = pNext(q);
2652        qq = result;
2653      }
2654      else
2655      {
2656        pNext(qq) = pNext(q);
2657        pIter(qq);
2658      }
2659      pNext(q) = pNext(pNext(q));
2660      pNext(qq) =NULL;
2661      p_SetComp(qq,0,r);
2662      p_SetmComp(qq,r);
2663    }
2664    else
2665    {
2666      pIter(q);
2667//      if (pGetComp(q) > k) pGetComp(q)--;
2668    }
2669  }
2670  return result;
2671}
2672
2673poly p_TakeOutComp(poly * p, int k, const ring r)
2674{
2675  poly q = *p,qq=NULL,result = NULL;
2676
2677  if (q==NULL) return NULL;
2678  BOOLEAN use_setmcomp=rOrd_SetCompRequiresSetm(r);
2679  if (p_GetComp(q,r)==k)
2680  {
2681    result = q;
2682    do
2683    {
2684      p_SetComp(q,0,r);
2685      if (use_setmcomp) p_SetmComp(q,r);
2686      qq = q;
2687      pIter(q);
2688    }
2689    while ((q!=NULL) && (p_GetComp(q,r)==k));
2690    *p = q;
2691    pNext(qq) = NULL;
2692  }
2693  if (q==NULL) return result;
2694  if (p_GetComp(q,r) > k)
2695  {
2696    p_SubComp(q,1,r);
2697    if (use_setmcomp) p_SetmComp(q,r);
2698  }
2699  poly pNext_q;
2700  while ((pNext_q=pNext(q))!=NULL)
2701  {
2702    if (p_GetComp(pNext_q,r)==k)
2703    {
2704      if (result==NULL)
2705      {
2706        result = pNext_q;
2707        qq = result;
2708      }
2709      else
2710      {
2711        pNext(qq) = pNext_q;
2712        pIter(qq);
2713      }
2714      pNext(q) = pNext(pNext_q);
2715      pNext(qq) =NULL;
2716      p_SetComp(qq,0,r);
2717      if (use_setmcomp) p_SetmComp(qq,r);
2718    }
2719    else
2720    {
2721      /*pIter(q);*/ q=pNext_q;
2722      if (p_GetComp(q,r) > k)
2723      {
2724        p_SubComp(q,1,r);
2725        if (use_setmcomp) p_SetmComp(q,r);
2726      }
2727    }
2728  }
2729  return result;
2730}
2731
2732// Splits *p into two polys: *q which consists of all monoms with
2733// component == comp and *p of all other monoms *lq == pLength(*q)
2734void p_TakeOutComp(poly *r_p, long comp, poly *r_q, int *lq, const ring r)
2735{
2736  spolyrec pp, qq;
2737  poly p, q, p_prev;
2738  int l = 0;
2739
2740#ifdef HAVE_ASSUME
2741  int lp = pLength(*r_p);
2742#endif
2743
2744  pNext(&pp) = *r_p;
2745  p = *r_p;
2746  p_prev = &pp;
2747  q = &qq;
2748
2749  while(p != NULL)
2750  {
2751    while (p_GetComp(p,r) == comp)
2752    {
2753      pNext(q) = p;
2754      pIter(q);
2755      p_SetComp(p, 0,r);
2756      p_SetmComp(p,r);
2757      pIter(p);
2758      l++;
2759      if (p == NULL)
2760      {
2761        pNext(p_prev) = NULL;
2762        goto Finish;
2763      }
2764    }
2765    pNext(p_prev) = p;
2766    p_prev = p;
2767    pIter(p);
2768  }
2769
2770  Finish:
2771  pNext(q) = NULL;
2772  *r_p = pNext(&pp);
2773  *r_q = pNext(&qq);
2774  *lq = l;
2775#ifdef HAVE_ASSUME
2776  assume(pLength(*r_p) + pLength(*r_q) == lp);
2777#endif
2778  p_Test(*r_p,r);
2779  p_Test(*r_q,r);
2780}
2781
2782void p_DeleteComp(poly * p,int k, const ring r)
2783{
2784  poly q;
2785
2786  while ((*p!=NULL) && (p_GetComp(*p,r)==k)) p_LmDelete(p,r);
2787  if (*p==NULL) return;
2788  q = *p;
2789  if (p_GetComp(q,r)>k)
2790  {
2791    p_SubComp(q,1,r);
2792    p_SetmComp(q,r);
2793  }
2794  while (pNext(q)!=NULL)
2795  {
2796    if (p_GetComp(pNext(q),r)==k)
2797      p_LmDelete(&(pNext(q)),r);
2798    else
2799    {
2800      pIter(q);
2801      if (p_GetComp(q,r)>k)
2802      {
2803        p_SubComp(q,1,r);
2804        p_SetmComp(q,r);
2805      }
2806    }
2807  }
2808}
2809/* -------------------------------------------------------- */
2810/*2
2811* change all global variables to fit the description of the new ring
2812*/
2813
2814void p_SetGlobals(const ring r, BOOLEAN complete)
2815{
2816  int i;
2817  if (r->ppNoether!=NULL) p_Delete(&r->ppNoether,r);
2818
2819  if (complete)
2820  {
2821    test &= ~ TEST_RINGDEP_OPTS;
2822    test |= r->options;
2823  }
2824}
2825//
2826// resets the pFDeg and pLDeg: if pLDeg is not given, it is
2827// set to currRing->pLDegOrig, i.e. to the respective LDegProc which
2828// only uses pFDeg (and not pDeg, or pTotalDegree, etc)
2829void pSetDegProcs(ring r, pFDegProc new_FDeg, pLDegProc new_lDeg)
2830{
2831  assume(new_FDeg != NULL);
2832  r->pFDeg = new_FDeg;
2833
2834  if (new_lDeg == NULL)
2835    new_lDeg = r->pLDegOrig;
2836
2837  r->pLDeg = new_lDeg;
2838}
2839
2840// restores pFDeg and pLDeg:
2841void pRestoreDegProcs(ring r, pFDegProc old_FDeg, pLDegProc old_lDeg)
2842{
2843  assume(old_FDeg != NULL && old_lDeg != NULL);
2844  r->pFDeg = old_FDeg;
2845  r->pLDeg = old_lDeg;
2846}
2847
2848/*-------- several access procedures to monomials -------------------- */
2849/*
2850* the module weights for std
2851*/
2852static pFDegProc pOldFDeg;
2853static pLDegProc pOldLDeg;
2854static intvec * pModW;
2855static BOOLEAN pOldLexOrder;
2856
2857static long pModDeg(poly p, ring r)
2858{
2859  long d=pOldFDeg(p, r);
2860  int c=p_GetComp(p, r);
2861  if ((c>0) && ((r->pModW)->range(c-1))) d+= (*(r->pModW))[c-1];
2862  return d;
2863  //return pOldFDeg(p, r)+(*pModW)[p_GetComp(p, r)-1];
2864}
2865
2866void p_SetModDeg(intvec *w, ring r)
2867{
2868  if (w!=NULL)
2869  {
2870    r->pModW = w;
2871    pOldFDeg = r->pFDeg;
2872    pOldLDeg = r->pLDeg;
2873    pOldLexOrder = r->pLexOrder;
2874    pSetDegProcs(r,pModDeg);
2875    r->pLexOrder = TRUE;
2876  }
2877  else
2878  {
2879    r->pModW = NULL;
2880    pRestoreDegProcs(r,pOldFDeg, pOldLDeg);
2881    r->pLexOrder = pOldLexOrder;
2882  }
2883}
2884
2885/*2
2886* handle memory request for sets of polynomials (ideals)
2887* l is the length of *p, increment is the difference (may be negative)
2888*/
2889void pEnlargeSet(poly* *p, int l, int increment)
2890{
2891  poly* h;
2892
2893  h=(poly*)omReallocSize((poly*)*p,l*sizeof(poly),(l+increment)*sizeof(poly));
2894  if (increment>0)
2895  {
2896    //for (i=l; i<l+increment; i++)
2897    //  h[i]=NULL;
2898    memset(&(h[l]),0,increment*sizeof(poly));
2899  }
2900  *p=h;
2901}
2902
2903/*2
2904*divides p1 by its leading coefficient
2905*/
2906void p_Norm(poly p1, const ring r)
2907{
2908#ifdef HAVE_RINGS
2909  if (rField_is_Ring(r))
2910  {
2911    if (!nIsUnit(pGetCoeff(p1))) return;
2912    // Werror("p_Norm not possible in the case of coefficient rings.");
2913  }
2914  else
2915#endif
2916  if (p1!=NULL)
2917  {
2918    if (pNext(p1)==NULL)
2919    {
2920      p_SetCoeff(p1,n_Init(1,r->cf),r);
2921      return;
2922    }
2923    poly h;
2924    if (!n_IsOne(pGetCoeff(p1),r->cf))
2925    {
2926      number k, c;
2927      n_Normalize(pGetCoeff(p1),r->cf);
2928      k = pGetCoeff(p1);
2929      c = n_Init(1,r->cf);
2930      pSetCoeff0(p1,c);
2931      h = pNext(p1);
2932      while (h!=NULL)
2933      {
2934        c=n_Div(pGetCoeff(h),k,r->cf);
2935        // no need to normalize: Z/p, R
2936        // normalize already in nDiv: Q_a, Z/p_a
2937        // remains: Q
2938        if (rField_is_Q(r) && (!n_IsOne(c,r->cf))) n_Normalize(c,r->cf);
2939        p_SetCoeff(h,c,r);
2940        pIter(h);
2941      }
2942      n_Delete(&k,r->cf);
2943    }
2944    else
2945    {
2946      //if (r->cf->cfNormalize != nDummy2) //TODO: OPTIMIZE
2947      {
2948        h = pNext(p1);
2949        while (h!=NULL)
2950        {
2951          n_Normalize(pGetCoeff(h),r->cf);
2952          pIter(h);
2953        }
2954      }
2955    }
2956  }
2957}
2958
2959/*2
2960*normalize all coefficients
2961*/
2962void p_Normalize(poly p,const ring r)
2963{
2964  if (rField_has_simple_inverse(r)) return; /* Z/p, GF(p,n), R, long R/C */
2965  while (p!=NULL)
2966  {
2967#ifdef LDEBUG
2968    if (currRing==r) {nTest(pGetCoeff(p));}
2969#endif
2970    n_Normalize(pGetCoeff(p),r->cf);
2971    pIter(p);
2972  }
2973}
2974
2975// splits p into polys with Exp(n) == 0 and Exp(n) != 0
2976// Poly with Exp(n) != 0 is reversed
2977static void p_SplitAndReversePoly(poly p, int n, poly *non_zero, poly *zero, const ring r)
2978{
2979  if (p == NULL)
2980  {
2981    *non_zero = NULL;
2982    *zero = NULL;
2983    return;
2984  }
2985  spolyrec sz;
2986  poly z, n_z, next;
2987  z = &sz;
2988  n_z = NULL;
2989
2990  while(p != NULL)
2991  {
2992    next = pNext(p);
2993    if (p_GetExp(p, n,r) == 0)
2994    {
2995      pNext(z) = p;
2996      pIter(z);
2997    }
2998    else
2999    {
3000      pNext(p) = n_z;
3001      n_z = p;
3002    }
3003    p = next;
3004  }
3005  pNext(z) = NULL;
3006  *zero = pNext(&sz);
3007  *non_zero = n_z;
3008}
3009/*3
3010* substitute the n-th variable by 1 in p
3011* destroy p
3012*/
3013static poly p_Subst1 (poly p,int n, const ring r)
3014{
3015  poly qq=NULL, result = NULL;
3016  poly zero=NULL, non_zero=NULL;
3017
3018  // reverse, so that add is likely to be linear
3019  p_SplitAndReversePoly(p, n, &non_zero, &zero,r);
3020
3021  while (non_zero != NULL)
3022  {
3023    assume(p_GetExp(non_zero, n,r) != 0);
3024    qq = non_zero;
3025    pIter(non_zero);
3026    qq->next = NULL;
3027    p_SetExp(qq,n,0,r);
3028    p_Setm(qq,r);
3029    result = p_Add_q(result,qq,r);
3030  }
3031  p = p_Add_q(result, zero,r);
3032  p_Test(p,r);
3033  return p;
3034}
3035
3036/*3
3037* substitute the n-th variable by number e in p
3038* destroy p
3039*/
3040static poly p_Subst2 (poly p,int n, number e, const ring r)
3041{
3042  assume( ! n_IsZero(e,r->cf) );
3043  poly qq,result = NULL;
3044  number nn, nm;
3045  poly zero, non_zero;
3046
3047  // reverse, so that add is likely to be linear
3048  p_SplitAndReversePoly(p, n, &non_zero, &zero,r);
3049
3050  while (non_zero != NULL)
3051  {
3052    assume(p_GetExp(non_zero, nm,r) != 0);
3053    qq = non_zero;
3054    pIter(non_zero);
3055    qq->next = NULL;
3056    n_Power(e, p_GetExp(qq, n, r), &nn,r->cf);
3057    nm = n_Mult(nn, pGetCoeff(qq),r->cf);
3058#ifdef HAVE_RINGS
3059    if (n_IsZero(nm,r->cf))
3060    {
3061      p_LmFree(&qq,r);
3062      n_Delete(&nm,r->cf);
3063    }
3064    else
3065#endif
3066    {
3067      p_SetCoeff(qq, nm,r);
3068      p_SetExp(qq, n, 0,r);
3069      p_Setm(qq,r);
3070      result = p_Add_q(result,qq,r);
3071    }
3072    n_Delete(&nn,r->cf);
3073  }
3074  p = p_Add_q(result, zero,r);
3075  p_Test(p,r);
3076  return p;
3077}
3078
3079
3080/* delete monoms whose n-th exponent is different from zero */
3081static poly p_Subst0(poly p, int n, const ring r)
3082{
3083  spolyrec res;
3084  poly h = &res;
3085  pNext(h) = p;
3086
3087  while (pNext(h)!=NULL)
3088  {
3089    if (p_GetExp(pNext(h),n,r)!=0)
3090    {
3091      p_LmDelete(&pNext(h),r);
3092    }
3093    else
3094    {
3095      pIter(h);
3096    }
3097  }
3098  p_Test(pNext(&res),r);
3099  return pNext(&res);
3100}
3101
3102/*2
3103* substitute the n-th variable by e in p
3104* destroy p
3105*/
3106poly p_Subst(poly p, int n, poly e, const ring r)
3107{
3108  if (e == NULL) return p_Subst0(p, n,r);
3109
3110  if (p_IsConstant(e,r))
3111  {
3112    if (n_IsOne(pGetCoeff(e),r->cf)) return p_Subst1(p,n,r);
3113    else return p_Subst2(p, n, pGetCoeff(e),r);
3114  }
3115
3116#ifdef HAVE_PLURAL
3117  if (rIsPluralRing(r))
3118  {
3119    return nc_pSubst(p,n,e,r);
3120  }
3121#endif
3122
3123  int exponent,i;
3124  poly h, res, m;
3125  int *me,*ee;
3126  number nu,nu1;
3127
3128  me=(int *)omAlloc((rVar(r)+1)*sizeof(int));
3129  ee=(int *)omAlloc((rVar(r)+1)*sizeof(int));
3130  if (e!=NULL) p_GetExpV(e,ee,r);
3131  res=NULL;
3132  h=p;
3133  while (h!=NULL)
3134  {
3135    if ((e!=NULL) || (p_GetExp(h,n,r)==0))
3136    {
3137      m=p_Head(h,r);
3138      p_GetExpV(m,me,r);
3139      exponent=me[n];
3140      me[n]=0;
3141      for(i=rVar(r);i>0;i--)
3142        me[i]+=exponent*ee[i];
3143      p_SetExpV(m,me,r);
3144      if (e!=NULL)
3145      {
3146        n_Power(pGetCoeff(e),exponent,&nu,r->cf);
3147        nu1=n_Mult(pGetCoeff(m),nu,r->cf);
3148        n_Delete(&nu,r->cf);
3149        p_SetCoeff(m,nu1,r);
3150      }
3151      res=p_Add_q(res,m,r);
3152    }
3153    p_LmDelete(&h,r);
3154  }
3155  omFreeSize((ADDRESS)me,(rVar(r)+1)*sizeof(int));
3156  omFreeSize((ADDRESS)ee,(rVar(r)+1)*sizeof(int));
3157  return res;
3158}
3159/*2
3160*returns a re-ordered copy of a polynomial, with permutation of the variables
3161*/
3162poly p_PermPoly (poly p, int * perm, const ring oldRing, const ring dst,
3163       nMapFunc nMap, int *par_perm, int OldPar)
3164{
3165  int OldpVariables = oldRing->N;
3166  poly result = NULL;
3167  poly result_last = NULL;
3168  poly aq=NULL; /* the map coefficient */
3169  poly qq; /* the mapped monomial */
3170
3171  while (p != NULL)
3172  {
3173    if ((OldPar==0)||(rField_is_GF(oldRing)))
3174    {
3175      qq = p_Init(dst);
3176      number n=nMap(pGetCoeff(p),oldRing->cf,dst->cf);
3177      if ((dst->minpoly!=NULL)
3178      && ((rField_is_Zp_a(dst)) || (rField_is_Q_a(dst))))
3179      {
3180        n_Normalize(n,dst->cf);
3181      }
3182      pGetCoeff(qq)=n;
3183    // coef may be zero:  pTest(qq);
3184    }
3185    else
3186    {
3187      qq=p_One(dst);
3188      WerrorS("longalg missing");
3189      #if 0
3190      aq=naPermNumber(pGetCoeff(p),par_perm,OldPar, oldRing);
3191      if ((dst->minpoly!=NULL)
3192      && ((rField_is_Zp_a(dst)) || (rField_is_Q_a(dst))))
3193      {
3194        poly tmp=aq;
3195        while (tmp!=NULL)
3196        {
3197          number n=pGetCoeff(tmp);
3198          n_Normalize(n,dst->cf);
3199          pGetCoeff(tmp)=n;
3200          pIter(tmp);
3201        }
3202      }
3203      p_Test(aq,dst);
3204      #endif
3205    }
3206    if (rRing_has_Comp(dst)) p_SetComp(qq, p_GetComp(p,oldRing),dst);
3207    if (n_IsZero(pGetCoeff(qq),dst->cf))
3208    {
3209      p_LmDelete(&qq,dst);
3210    }
3211    else
3212    {
3213      int i;
3214      int mapped_to_par=0;
3215      for(i=1; i<=OldpVariables; i++)
3216      {
3217        int e=p_GetExp(p,i,oldRing);
3218        if (e!=0)
3219        {
3220          if (perm==NULL)
3221          {
3222            p_SetExp(qq,i, e, dst);
3223          }
3224          else if (perm[i]>0)
3225            p_AddExp(qq,perm[i], e/*p_GetExp( p,i,oldRing)*/, dst);
3226          else if (perm[i]<0)
3227          {
3228            if (rField_is_GF(dst))
3229            {
3230              number c=pGetCoeff(qq);
3231              number ee=n_Par(1,dst->cf);
3232              number eee;n_Power(ee,e,&eee,dst->cf); //nfDelete(ee,dst);
3233              ee=n_Mult(c,eee,dst->cf);
3234              //nfDelete(c,dst);nfDelete(eee,dst);
3235              pSetCoeff0(qq,ee);
3236            }
3237            else
3238            {
3239              WerrorS("longalg missing");
3240              #if 0
3241              lnumber c=(lnumber)pGetCoeff(qq);
3242              if (c->z->next==NULL)
3243                p_AddExp(c->z,-perm[i],e/*p_GetExp( p,i,oldRing)*/,dst->algring);
3244              else /* more difficult: we have really to multiply: */
3245              {
3246                lnumber mmc=(lnumber)naInit(1,dst);
3247                p_SetExp(mmc->z,-perm[i],e/*p_GetExp( p,i,oldRing)*/,dst->algring);
3248                p_Setm(mmc->z,dst->algring->cf);
3249                pGetCoeff(qq)=n_Mult((number)c,(number)mmc,dst->cf);
3250                n_Delete((number *)&c,dst->cf);
3251                n_Delete((number *)&mmc,dst->cf);
3252              }
3253              mapped_to_par=1;
3254              #endif
3255            }
3256          }
3257          else
3258          {
3259            /* this variable maps to 0 !*/
3260            p_LmDelete(&qq,dst);
3261            break;
3262          }
3263        }
3264      }
3265      if (mapped_to_par
3266      && (dst->minpoly!=NULL))
3267      {
3268        number n=pGetCoeff(qq);
3269        n_Normalize(n,dst->cf);
3270        pGetCoeff(qq)=n;
3271      }
3272    }
3273    pIter(p);
3274#if 1
3275    if (qq!=NULL)
3276    {
3277      p_Setm(qq,dst);
3278      p_Test(aq,dst);
3279      p_Test(qq,dst);
3280      if (aq!=NULL) qq=p_Mult_q(aq,qq,dst);
3281      aq = qq;
3282      while (pNext(aq) != NULL) pIter(aq);
3283      if (result_last==NULL)
3284      {
3285        result=qq;
3286      }
3287      else
3288      {
3289        pNext(result_last)=qq;
3290      }
3291      result_last=aq;
3292      aq = NULL;
3293    }
3294    else if (aq!=NULL)
3295    {
3296      p_Delete(&aq,dst);
3297    }
3298  }
3299  result=p_SortAdd(result,dst);
3300#else
3301  //  if (qq!=NULL)
3302  //  {
3303  //    pSetm(qq);
3304  //    pTest(qq);
3305  //    pTest(aq);
3306  //    if (aq!=NULL) qq=pMult(aq,qq);
3307  //    aq = qq;
3308  //    while (pNext(aq) != NULL) pIter(aq);
3309  //    pNext(aq) = result;
3310  //    aq = NULL;
3311  //    result = qq;
3312  //  }
3313  //  else if (aq!=NULL)
3314  //  {
3315  //    pDelete(&aq);
3316  //  }
3317  //}
3318  //p = result;
3319  //result = NULL;
3320  //while (p != NULL)
3321  //{
3322  //  qq = p;
3323  //  pIter(p);
3324  //  qq->next = NULL;
3325  //  result = pAdd(result, qq);
3326  //}
3327#endif
3328  p_Test(result,dst);
3329  return result;
3330}
3331
3332/***************************************************************
3333 *
3334 * p_ShallowDelete
3335 *
3336 ***************************************************************/
3337#undef LINKAGE
3338#define LINKAGE
3339#undef p_Delete__T
3340#define p_Delete__T p_ShallowDelete
3341#undef n_Delete__T
3342#define n_Delete__T(n, r) ((void)0)
3343
3344#include <polys/templates/p_Delete__T.cc>
3345
3346#ifdef HAVE_RINGS
3347/* TRUE iff LT(f) | LT(g) */
3348BOOLEAN p_DivisibleByRingCase(poly f, poly g, const ring r)
3349{
3350  int exponent;
3351  for(int i = (int)r->N; i; i--)
3352  {
3353    exponent = p_GetExp(g, i, r) - p_GetExp(f, i, r);
3354    if (exponent < 0) return FALSE;
3355  }
3356  return n_DivBy(p_GetCoeff(g,r), p_GetCoeff(f,r),r->cf);
3357}
3358#endif
Note: See TracBrowser for help on using the repository browser.