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

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