source: git/polys/monomials/p_polys.cc @ deca086

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