source: git/libpolys/polys/monomials/p_polys.cc @ 8e45403

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