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

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