source: git/libpolys/polys/monomials/p_polys.cc @ 7eb7b5

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