source: git/libpolys/polys/monomials/p_polys.cc @ 88cceb

spielwiese
Last change on this file since 88cceb was 88cceb, checked in by Hans Schoenemann <hannes@…>, 9 years ago
fix: n_Lcm is not n_NormalizeHelper
  • Property mode set to 100644
File size: 97.8 KB
Line 
1/****************************************
2*  Computer Algebra System SINGULAR     *
3****************************************/
4/***************************************************************
5 *  File:    p_polys.cc
6 *  Purpose: implementation of ring independent poly procedures?
7 *  Author:  obachman (Olaf Bachmann)
8 *  Created: 8/00
9 *******************************************************************/
10
11
12
13
14
15
16#include <ctype.h>
17
18#include <omalloc/omalloc.h>
19
20#include <misc/auxiliary.h>
21
22#include <misc/options.h>
23#include <misc/intvec.h>
24
25#include <coeffs/longrat.h> // ???
26#include <coeffs/ffields.h>
27
28#include <polys/PolyEnumerator.h>
29
30#define TRANSEXT_PRIVATES
31
32#include <polys/ext_fields/transext.h>
33#include <polys/ext_fields/algext.h>
34
35#include <polys/weight.h>
36#include <polys/simpleideals.h>
37
38#include "ring.h"
39#include "p_polys.h"
40
41#include <polys/templates/p_MemCmp.h>
42#include <polys/templates/p_MemAdd.h>
43#include <polys/templates/p_MemCopy.h>
44
45
46// #include <???/ideals.h>
47// #include <???/int64vec.h>
48
49#ifndef SING_NDEBUG
50// #include <???/febase.h>
51#endif
52
53#ifdef HAVE_PLURAL
54#include "nc/nc.h"
55#include "nc/sca.h"
56#endif
57
58#include "coeffrings.h"
59#include "clapsing.h"
60
61#define ADIDEBUG 0
62
63/*
64 * lift ideal with coeffs over Z (mod N) to Q via Farey
65 */
66poly p_Farey(poly p, number N, const ring r)
67{
68  poly h=p_Copy(p,r);
69  poly hh=h;
70  while(h!=NULL)
71  {
72    number c=pGetCoeff(h);
73    pSetCoeff0(h,n_Farey(c,N,r->cf));
74    n_Delete(&c,r->cf);
75    pIter(h);
76  }
77  while((hh!=NULL)&&(n_IsZero(pGetCoeff(hh),r->cf)))
78  {
79    p_LmDelete(&hh,r);
80  }
81  h=hh;
82  while((h!=NULL) && (pNext(h)!=NULL))
83  {
84    if(n_IsZero(pGetCoeff(pNext(h)),r->cf))
85    {
86      p_LmDelete(&pNext(h),r);
87    }
88    else pIter(h);
89  }
90  return hh;
91}
92/*2
93* xx,q: arrays of length 0..rl-1
94* xx[i]: SB mod q[i]
95* assume: char=0
96* assume: q[i]!=0
97* destroys xx
98*/
99poly p_ChineseRemainder(poly *xx, number *x,number *q, int rl, const ring R)
100{
101  poly r,h,hh;
102  int j;
103  poly  res_p=NULL;
104  loop
105  {
106    /* search the lead term */
107    r=NULL;
108    for(j=rl-1;j>=0;j--)
109    {
110      h=xx[j];
111      if ((h!=NULL)
112      &&((r==NULL)||(p_LmCmp(r,h,R)==-1)))
113        r=h;
114    }
115    /* nothing found -> return */
116    if (r==NULL) break;
117    /* create the monomial in h */
118    h=p_Head(r,R);
119    /* collect the coeffs in x[..]*/
120    for(j=rl-1;j>=0;j--)
121    {
122      hh=xx[j];
123      if ((hh!=NULL) && (p_LmCmp(r,hh,R)==0))
124      {
125        x[j]=pGetCoeff(hh);
126        hh=p_LmFreeAndNext(hh,R);
127        xx[j]=hh;
128      }
129      else
130        x[j]=n_Init(0, R);
131    }
132    number n=n_ChineseRemainderSym(x,q,rl,TRUE,R->cf);
133    for(j=rl-1;j>=0;j--)
134    {
135      x[j]=NULL; // nlInit(0...) takes no memory
136    }
137    if (n_IsZero(n,R)) p_Delete(&h,R);
138    else
139    {
140      //Print("new mon:");pWrite(h);
141      p_SetCoeff(h,n,R);
142      pNext(h)=res_p;
143      res_p=h; // building res_p in reverse order!
144    }
145  }
146  res_p=pReverse(res_p);
147  p_Test(res_p, R);
148  return res_p;
149}
150/***************************************************************
151 *
152 * Completing what needs to be set for the monomial
153 *
154 ***************************************************************/
155// this is special for the syz stuff
156static int* _components = NULL;
157static long* _componentsShifted = NULL;
158static int _componentsExternal = 0;
159
160BOOLEAN pSetm_error=0;
161
162#ifndef SING_NDEBUG
163# define MYTEST 0
164#else /* ifndef SING_NDEBUG */
165# define MYTEST 0
166#endif /* ifndef SING_NDEBUG */
167
168void p_Setm_General(poly p, const ring r)
169{
170  p_LmCheckPolyRing(p, r);
171  int pos=0;
172  if (r->typ!=NULL)
173  {
174    loop
175    {
176      unsigned long ord=0;
177      sro_ord* o=&(r->typ[pos]);
178      switch(o->ord_typ)
179      {
180        case ro_dp:
181        {
182          int a,e;
183          a=o->data.dp.start;
184          e=o->data.dp.end;
185          for(int i=a;i<=e;i++) ord+=p_GetExp(p,i,r);
186          p->exp[o->data.dp.place]=ord;
187          break;
188        }
189        case ro_wp_neg:
190          ord=POLY_NEGWEIGHT_OFFSET;
191          // no break;
192        case ro_wp:
193        {
194          int a,e;
195          a=o->data.wp.start;
196          e=o->data.wp.end;
197          int *w=o->data.wp.weights;
198#if 1
199          for(int i=a;i<=e;i++) ord+=((unsigned long)p_GetExp(p,i,r))*((unsigned long)w[i-a]);
200#else
201          long ai;
202          int ei,wi;
203          for(int i=a;i<=e;i++)
204          {
205             ei=p_GetExp(p,i,r);
206             wi=w[i-a];
207             ai=ei*wi;
208             if (ai/ei!=wi) pSetm_error=TRUE;
209             ord+=ai;
210             if (ord<ai) pSetm_error=TRUE;
211          }
212#endif
213          p->exp[o->data.wp.place]=ord;
214          break;
215        }
216        case ro_am:
217        {
218          ord = POLY_NEGWEIGHT_OFFSET;
219          const short a=o->data.am.start;
220          const short e=o->data.am.end;
221          const int * w=o->data.am.weights;
222#if 1
223          for(short i=a; i<=e; i++, w++)
224            ord += ((*w) * p_GetExp(p,i,r));
225#else
226          long ai;
227          int ei,wi;
228          for(short i=a;i<=e;i++)
229          {
230             ei=p_GetExp(p,i,r);
231             wi=w[i-a];
232             ai=ei*wi;
233             if (ai/ei!=wi) pSetm_error=TRUE;
234             ord += ai;
235             if (ord<ai) pSetm_error=TRUE;
236          }
237#endif
238          const int c = p_GetComp(p,r);
239
240          const short len_gen= o->data.am.len_gen;
241
242          if ((c > 0) && (c <= len_gen))
243          {
244            assume( w == o->data.am.weights_m );
245            assume( w[0] == len_gen );
246            ord += w[c];
247          }
248
249          p->exp[o->data.am.place] = ord;
250          break;
251        }
252      case ro_wp64:
253        {
254          int64 ord=0;
255          int a,e;
256          a=o->data.wp64.start;
257          e=o->data.wp64.end;
258          int64 *w=o->data.wp64.weights64;
259          int64 ei,wi,ai;
260          for(int i=a;i<=e;i++)
261          {
262            //Print("exp %d w %d \n",p_GetExp(p,i,r),(int)w[i-a]);
263            //ord+=((int64)p_GetExp(p,i,r))*w[i-a];
264            ei=(int64)p_GetExp(p,i,r);
265            wi=w[i-a];
266            ai=ei*wi;
267            if(ei!=0 && ai/ei!=wi)
268            {
269              pSetm_error=TRUE;
270              #if SIZEOF_LONG == 4
271              Print("ai %lld, wi %lld\n",ai,wi);
272              #else
273              Print("ai %ld, wi %ld\n",ai,wi);
274              #endif
275            }
276            ord+=ai;
277            if (ord<ai)
278            {
279              pSetm_error=TRUE;
280              #if SIZEOF_LONG == 4
281              Print("ai %lld, ord %lld\n",ai,ord);
282              #else
283              Print("ai %ld, ord %ld\n",ai,ord);
284              #endif
285            }
286          }
287          int64 mask=(int64)0x7fffffff;
288          long a_0=(long)(ord&mask); //2^31
289          long a_1=(long)(ord >>31 ); /*(ord/(mask+1));*/
290
291          //Print("mask: %x,  ord: %d,  a_0: %d,  a_1: %d\n"
292          //,(int)mask,(int)ord,(int)a_0,(int)a_1);
293                    //Print("mask: %d",mask);
294
295          p->exp[o->data.wp64.place]=a_1;
296          p->exp[o->data.wp64.place+1]=a_0;
297//            if(p_Setm_error) Print("***************************\n
298//                                    ***************************\n
299//                                    **WARNING: overflow error**\n
300//                                    ***************************\n
301//                                    ***************************\n");
302          break;
303        }
304        case ro_cp:
305        {
306          int a,e;
307          a=o->data.cp.start;
308          e=o->data.cp.end;
309          int pl=o->data.cp.place;
310          for(int i=a;i<=e;i++) { p->exp[pl]=p_GetExp(p,i,r); pl++; }
311          break;
312        }
313        case ro_syzcomp:
314        {
315          int c=p_GetComp(p,r);
316          long sc = c;
317          int* Components = (_componentsExternal ? _components :
318                             o->data.syzcomp.Components);
319          long* ShiftedComponents = (_componentsExternal ? _componentsShifted:
320                                     o->data.syzcomp.ShiftedComponents);
321          if (ShiftedComponents != NULL)
322          {
323            assume(Components != NULL);
324            assume(c == 0 || Components[c] != 0);
325            sc = ShiftedComponents[Components[c]];
326            assume(c == 0 || sc != 0);
327          }
328          p->exp[o->data.syzcomp.place]=sc;
329          break;
330        }
331        case ro_syz:
332        {
333          const unsigned long c = p_GetComp(p, r);
334          const short place = o->data.syz.place;
335          const int limit = o->data.syz.limit;
336
337          if (c > (unsigned long)limit)
338            p->exp[place] = o->data.syz.curr_index;
339          else if (c > 0)
340          {
341            assume( (1 <= c) && (c <= (unsigned long)limit) );
342            p->exp[place]= o->data.syz.syz_index[c];
343          }
344          else
345          {
346            assume(c == 0);
347            p->exp[place]= 0;
348          }
349          break;
350        }
351        // Prefix for Induced Schreyer ordering
352        case ro_isTemp: // Do nothing?? (to be removed into suffix later on...?)
353        {
354          assume(p != NULL);
355
356#ifndef SING_NDEBUG
357#if MYTEST
358          Print("p_Setm_General: ro_isTemp ord: pos: %d, p: ", pos);  p_DebugPrint(p, r, r, 1);
359#endif
360#endif
361          int c = p_GetComp(p, r);
362
363          assume( c >= 0 );
364
365          // Let's simulate case ro_syz above....
366          // Should accumulate (by Suffix) and be a level indicator
367          const int* const pVarOffset = o->data.isTemp.pVarOffset;
368
369          assume( pVarOffset != NULL );
370
371          // TODO: Can this be done in the suffix???
372          for( int i = 1; i <= r->N; i++ ) // No v[0] here!!!
373          {
374            const int vo = pVarOffset[i];
375            if( vo != -1) // TODO: optimize: can be done once!
376            {
377              // Hans! Please don't break it again! p_SetExp(p, ..., r, vo) is correct:
378              p_SetExp(p, p_GetExp(p, i, r), r, vo); // copy put them verbatim
379              // Hans! Please don't break it again! p_GetExp(p, r, vo) is correct:
380              assume( p_GetExp(p, r, vo) == p_GetExp(p, i, r) ); // copy put them verbatim
381            }
382          }
383#ifndef SING_NDEBUG
384          for( int i = 1; i <= r->N; i++ ) // No v[0] here!!!
385          {
386            const int vo = pVarOffset[i];
387            if( vo != -1) // TODO: optimize: can be done once!
388            {
389              // Hans! Please don't break it again! p_GetExp(p, r, vo) is correct:
390              assume( p_GetExp(p, r, vo) == p_GetExp(p, i, r) ); // copy put them verbatim
391            }
392          }
393#if MYTEST
394//          if( p->exp[o->data.isTemp.start] > 0 )
395            PrintS("after Values: "); p_DebugPrint(p, r, r, 1);
396#endif
397#endif
398          break;
399        }
400
401        // Suffix for Induced Schreyer ordering
402        case ro_is:
403        {
404#ifndef SING_NDEBUG
405#if MYTEST
406          Print("p_Setm_General: ro_is ord: pos: %d, p: ", pos);  p_DebugPrint(p, r, r, 1);
407#endif
408#endif
409
410          assume(p != NULL);
411
412          int c = p_GetComp(p, r);
413
414          assume( c >= 0 );
415          const ideal F = o->data.is.F;
416          const int limit = o->data.is.limit;
417          assume( limit >= 0 );
418          const int start = o->data.is.start;
419
420          if( F != NULL && c > limit )
421          {
422#ifndef SING_NDEBUG
423#if MYTEST
424            Print("p_Setm_General: ro_is : in rSetm: pos: %d, c: %d >  limit: %d\n", c, pos, limit); // p_DebugPrint(p, r, r, 1);
425            PrintS("preComputed Values: ");
426            p_DebugPrint(p, r, r, 1);
427#endif
428#endif
429//          if( c > limit ) // BUG???
430            p->exp[start] = 1;
431//          else
432//            p->exp[start] = 0;
433
434
435            c -= limit;
436            assume( c > 0 );
437            c--;
438
439            if( c >= IDELEMS(F) )
440              break;
441
442            assume( c < IDELEMS(F) ); // What about others???
443
444            const poly pp = F->m[c]; // get reference monomial!!!
445
446            if(pp == NULL)
447              break;
448
449            assume(pp != NULL);
450
451#ifndef SING_NDEBUG
452#if MYTEST
453            Print("Respective F[c - %d: %d] pp: ", limit, c);
454            p_DebugPrint(pp, r, r, 1);
455#endif
456#endif
457
458            const int end = o->data.is.end;
459            assume(start <= end);
460
461
462//          const int st = o->data.isTemp.start;
463
464#ifndef SING_NDEBUG
465            Print("p_Setm_General: is(-Temp-) :: c: %d, limit: %d, [st:%d] ===>>> %ld\n", c, limit, start, p->exp[start]);
466#endif
467
468            // p_ExpVectorAdd(p, pp, r);
469
470            for( int i = start; i <= end; i++) // v[0] may be here...
471              p->exp[i] += pp->exp[i]; // !!!!!!!! ADD corresponding LT(F)
472
473            // p_MemAddAdjust(p, ri);
474            if (r->NegWeightL_Offset != NULL)
475            {
476              for (int i=r->NegWeightL_Size-1; i>=0; i--)
477              {
478                const int _i = r->NegWeightL_Offset[i];
479                if( start <= _i && _i <= end )
480                  p->exp[_i] -= POLY_NEGWEIGHT_OFFSET;
481              }
482            }
483
484
485#ifndef SING_NDEBUG
486            const int* const pVarOffset = o->data.is.pVarOffset;
487
488            assume( pVarOffset != NULL );
489
490            for( int i = 1; i <= r->N; i++ ) // No v[0] here!!!
491            {
492              const int vo = pVarOffset[i];
493              if( vo != -1) // TODO: optimize: can be done once!
494                // Hans! Please don't break it again! p_GetExp(p/pp, r, vo) is correct:
495                assume( p_GetExp(p, r, vo) == (p_GetExp(p, i, r) + p_GetExp(pp, r, vo)) );
496            }
497            // TODO: how to check this for computed values???
498#if MYTEST
499            PrintS("Computed Values: "); p_DebugPrint(p, r, r, 1);
500#endif
501#endif
502          } else
503          {
504            p->exp[start] = 0; //!!!!????? where?????
505
506            const int* const pVarOffset = o->data.is.pVarOffset;
507
508            // What about v[0] - component: it will be added later by
509            // suffix!!!
510            // TODO: Test it!
511            const int vo = pVarOffset[0];
512            if( vo != -1 )
513              p->exp[vo] = c; // initial component v[0]!
514
515#ifndef SING_NDEBUG
516#if MYTEST
517            Print("ELSE p_Setm_General: ro_is :: c: %d <= limit: %d, vo: %d, exp: %d\n", c, limit, vo, p->exp[vo]);
518            p_DebugPrint(p, r, r, 1);
519#endif
520#endif
521          }
522
523          break;
524        }
525        default:
526          dReportError("wrong ord in rSetm:%d\n",o->ord_typ);
527          return;
528      }
529      pos++;
530      if (pos == r->OrdSize) return;
531    }
532  }
533}
534
535void p_Setm_Syz(poly p, ring r, int* Components, long* ShiftedComponents)
536{
537  _components = Components;
538  _componentsShifted = ShiftedComponents;
539  _componentsExternal = 1;
540  p_Setm_General(p, r);
541  _componentsExternal = 0;
542}
543
544// dummy for lp, ls, etc
545void p_Setm_Dummy(poly p, const ring r)
546{
547  p_LmCheckPolyRing(p, r);
548}
549
550// for dp, Dp, ds, etc
551void p_Setm_TotalDegree(poly p, const ring r)
552{
553  p_LmCheckPolyRing(p, r);
554  p->exp[r->pOrdIndex] = p_Totaldegree(p, r);
555}
556
557// for wp, Wp, ws, etc
558void p_Setm_WFirstTotalDegree(poly p, const ring r)
559{
560  p_LmCheckPolyRing(p, r);
561  p->exp[r->pOrdIndex] = p_WFirstTotalDegree(p, r);
562}
563
564p_SetmProc p_GetSetmProc(ring r)
565{
566  // covers lp, rp, ls,
567  if (r->typ == NULL) return p_Setm_Dummy;
568
569  if (r->OrdSize == 1)
570  {
571    if (r->typ[0].ord_typ == ro_dp &&
572        r->typ[0].data.dp.start == 1 &&
573        r->typ[0].data.dp.end == r->N &&
574        r->typ[0].data.dp.place == r->pOrdIndex)
575      return p_Setm_TotalDegree;
576    if (r->typ[0].ord_typ == ro_wp &&
577        r->typ[0].data.wp.start == 1 &&
578        r->typ[0].data.wp.end == r->N &&
579        r->typ[0].data.wp.place == r->pOrdIndex &&
580        r->typ[0].data.wp.weights == r->firstwv)
581      return p_Setm_WFirstTotalDegree;
582  }
583  return p_Setm_General;
584}
585
586
587/* -------------------------------------------------------------------*/
588/* several possibilities for pFDeg: the degree of the head term       */
589
590/* comptible with ordering */
591long p_Deg(poly a, const ring r)
592{
593  p_LmCheckPolyRing(a, r);
594//  assume(p_GetOrder(a, r) == p_WTotaldegree(a, r)); // WRONG assume!
595  return p_GetOrder(a, r);
596}
597
598// p_WTotalDegree for weighted orderings
599// whose first block covers all variables
600long p_WFirstTotalDegree(poly p, const ring r)
601{
602  int i;
603  long sum = 0;
604
605  for (i=1; i<= r->firstBlockEnds; i++)
606  {
607    sum += p_GetExp(p, i, r)*r->firstwv[i-1];
608  }
609  return sum;
610}
611
612/*2
613* compute the degree of the leading monomial of p
614* with respect to weigths from the ordering
615* the ordering is not compatible with degree so do not use p->Order
616*/
617long p_WTotaldegree(poly p, const ring r)
618{
619  p_LmCheckPolyRing(p, r);
620  int i, k;
621  long j =0;
622
623  // iterate through each block:
624  for (i=0;r->order[i]!=0;i++)
625  {
626    int b0=r->block0[i];
627    int b1=r->block1[i];
628    switch(r->order[i])
629    {
630      case ringorder_M:
631        for (k=b0 /*r->block0[i]*/;k<=b1 /*r->block1[i]*/;k++)
632        { // in jedem block:
633          j+= p_GetExp(p,k,r)*r->wvhdl[i][k - b0 /*r->block0[i]*/]*r->OrdSgn;
634        }
635        break;
636      case ringorder_wp:
637      case ringorder_ws:
638      case ringorder_Wp:
639      case ringorder_Ws:
640        for (k=b0 /*r->block0[i]*/;k<=b1 /*r->block1[i]*/;k++)
641        { // in jedem block:
642          j+= p_GetExp(p,k,r)*r->wvhdl[i][k - b0 /*r->block0[i]*/];
643        }
644        break;
645      case ringorder_lp:
646      case ringorder_ls:
647      case ringorder_rs:
648      case ringorder_dp:
649      case ringorder_ds:
650      case ringorder_Dp:
651      case ringorder_Ds:
652      case ringorder_rp:
653        for (k=b0 /*r->block0[i]*/;k<=b1 /*r->block1[i]*/;k++)
654        {
655          j+= p_GetExp(p,k,r);
656        }
657        break;
658      case ringorder_a64:
659        {
660          int64* w=(int64*)r->wvhdl[i];
661          for (k=0;k<=(b1 /*r->block1[i]*/ - b0 /*r->block0[i]*/);k++)
662          {
663            //there should be added a line which checks if w[k]>2^31
664            j+= p_GetExp(p,k+1, r)*(long)w[k];
665          }
666          //break;
667          return j;
668        }
669      case ringorder_c:
670      case ringorder_C:
671      case ringorder_S:
672      case ringorder_s:
673      case ringorder_aa:
674      case ringorder_IS:
675        break;
676      case ringorder_a:
677        for (k=b0 /*r->block0[i]*/;k<=b1 /*r->block1[i]*/;k++)
678        { // only one line
679          j+= p_GetExp(p,k, r)*r->wvhdl[i][ k- b0 /*r->block0[i]*/];
680        }
681        //break;
682        return j;
683
684#ifndef SING_NDEBUG
685      default:
686        Print("missing order %d in p_WTotaldegree\n",r->order[i]);
687        break;
688#endif
689    }
690  }
691  return  j;
692}
693
694long p_DegW(poly p, const short *w, const ring R)
695{
696  assume( p_Test(p, R) );
697  assume( w != NULL );
698  long r=-LONG_MAX;
699
700  while (p!=NULL)
701  {
702    long t=totaldegreeWecart_IV(p,R,w);
703    if (t>r) r=t;
704    pIter(p);
705  }
706  return r;
707}
708
709int p_Weight(int i, const ring r)
710{
711  if ((r->firstwv==NULL) || (i>r->firstBlockEnds))
712  {
713    return 1;
714  }
715  return r->firstwv[i-1];
716}
717
718long p_WDegree(poly p, const ring r)
719{
720  if (r->firstwv==NULL) return p_Totaldegree(p, r);
721  p_LmCheckPolyRing(p, r);
722  int i;
723  long j =0;
724
725  for(i=1;i<=r->firstBlockEnds;i++)
726    j+=p_GetExp(p, i, r)*r->firstwv[i-1];
727
728  for (;i<=rVar(r);i++)
729    j+=p_GetExp(p,i, r)*p_Weight(i, r);
730
731  return j;
732}
733
734
735/* ---------------------------------------------------------------------*/
736/* several possibilities for pLDeg: the maximal degree of a monomial in p*/
737/*  compute in l also the pLength of p                                   */
738
739/*2
740* compute the length of a polynomial (in l)
741* and the degree of the monomial with maximal degree: the last one
742*/
743long pLDeg0(poly p,int *l, const ring r)
744{
745  p_CheckPolyRing(p, r);
746  long k= p_GetComp(p, r);
747  int ll=1;
748
749  if (k > 0)
750  {
751    while ((pNext(p)!=NULL) && (p_GetComp(pNext(p), r)==k))
752    {
753      pIter(p);
754      ll++;
755    }
756  }
757  else
758  {
759     while (pNext(p)!=NULL)
760     {
761       pIter(p);
762       ll++;
763     }
764  }
765  *l=ll;
766  return r->pFDeg(p, r);
767}
768
769/*2
770* compute the length of a polynomial (in l)
771* and the degree of the monomial with maximal degree: the last one
772* but search in all components before syzcomp
773*/
774long pLDeg0c(poly p,int *l, const ring r)
775{
776  assume(p!=NULL);
777#ifdef PDEBUG
778  _p_Test(p,r,PDEBUG);
779#endif
780  p_CheckPolyRing(p, r);
781  long o;
782  int ll=1;
783
784  if (! rIsSyzIndexRing(r))
785  {
786    while (pNext(p) != NULL)
787    {
788      pIter(p);
789      ll++;
790    }
791    o = r->pFDeg(p, r);
792  }
793  else
794  {
795    int curr_limit = rGetCurrSyzLimit(r);
796    poly pp = p;
797    while ((p=pNext(p))!=NULL)
798    {
799      if (p_GetComp(p, r)<=curr_limit/*syzComp*/)
800        ll++;
801      else break;
802      pp = p;
803    }
804#ifdef PDEBUG
805    _p_Test(pp,r,PDEBUG);
806#endif
807    o = r->pFDeg(pp, r);
808  }
809  *l=ll;
810  return o;
811}
812
813/*2
814* compute the length of a polynomial (in l)
815* and the degree of the monomial with maximal degree: the first one
816* this works for the polynomial case with degree orderings
817* (both c,dp and dp,c)
818*/
819long pLDegb(poly p,int *l, const ring r)
820{
821  p_CheckPolyRing(p, r);
822  long k= p_GetComp(p, r);
823  long o = r->pFDeg(p, r);
824  int ll=1;
825
826  if (k != 0)
827  {
828    while (((p=pNext(p))!=NULL) && (p_GetComp(p, r)==k))
829    {
830      ll++;
831    }
832  }
833  else
834  {
835    while ((p=pNext(p)) !=NULL)
836    {
837      ll++;
838    }
839  }
840  *l=ll;
841  return o;
842}
843
844/*2
845* compute the length of a polynomial (in l)
846* and the degree of the monomial with maximal degree:
847* this is NOT the last one, we have to look for it
848*/
849long pLDeg1(poly p,int *l, const ring r)
850{
851  p_CheckPolyRing(p, r);
852  long k= p_GetComp(p, r);
853  int ll=1;
854  long  t,max;
855
856  max=r->pFDeg(p, r);
857  if (k > 0)
858  {
859    while (((p=pNext(p))!=NULL) && (p_GetComp(p, r)==k))
860    {
861      t=r->pFDeg(p, r);
862      if (t>max) max=t;
863      ll++;
864    }
865  }
866  else
867  {
868    while ((p=pNext(p))!=NULL)
869    {
870      t=r->pFDeg(p, r);
871      if (t>max) max=t;
872      ll++;
873    }
874  }
875  *l=ll;
876  return max;
877}
878
879/*2
880* compute the length of a polynomial (in l)
881* and the degree of the monomial with maximal degree:
882* this is NOT the last one, we have to look for it
883* in all components
884*/
885long pLDeg1c(poly p,int *l, const ring r)
886{
887  p_CheckPolyRing(p, r);
888  int ll=1;
889  long  t,max;
890
891  max=r->pFDeg(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=r->pFDeg(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=r->pFDeg(p, r))>max) max=t;
910      ll++;
911    }
912  }
913  *l=ll;
914  return max;
915}
916
917// like pLDeg1, only pFDeg == pDeg
918long pLDeg1_Deg(poly p,int *l, const ring r)
919{
920  assume(r->pFDeg == p_Deg);
921  p_CheckPolyRing(p, r);
922  long k= p_GetComp(p, r);
923  int ll=1;
924  long  t,max;
925
926  max=p_GetOrder(p, r);
927  if (k > 0)
928  {
929    while (((p=pNext(p))!=NULL) && (p_GetComp(p, r)==k))
930    {
931      t=p_GetOrder(p, r);
932      if (t>max) max=t;
933      ll++;
934    }
935  }
936  else
937  {
938    while ((p=pNext(p))!=NULL)
939    {
940      t=p_GetOrder(p, r);
941      if (t>max) max=t;
942      ll++;
943    }
944  }
945  *l=ll;
946  return max;
947}
948
949long pLDeg1c_Deg(poly p,int *l, const ring r)
950{
951  assume(r->pFDeg == p_Deg);
952  p_CheckPolyRing(p, r);
953  int ll=1;
954  long  t,max;
955
956  max=p_GetOrder(p, r);
957  if (rIsSyzIndexRing(r))
958  {
959    long limit = rGetCurrSyzLimit(r);
960    while ((p=pNext(p))!=NULL)
961    {
962      if (p_GetComp(p, r)<=limit)
963      {
964        if ((t=p_GetOrder(p, r))>max) max=t;
965        ll++;
966      }
967      else break;
968    }
969  }
970  else
971  {
972    while ((p=pNext(p))!=NULL)
973    {
974      if ((t=p_GetOrder(p, r))>max) max=t;
975      ll++;
976    }
977  }
978  *l=ll;
979  return max;
980}
981
982// like pLDeg1, only pFDeg == pTotoalDegree
983long pLDeg1_Totaldegree(poly p,int *l, const ring r)
984{
985  p_CheckPolyRing(p, r);
986  long k= p_GetComp(p, r);
987  int ll=1;
988  long  t,max;
989
990  max=p_Totaldegree(p, r);
991  if (k > 0)
992  {
993    while (((p=pNext(p))!=NULL) && (p_GetComp(p, r)==k))
994    {
995      t=p_Totaldegree(p, r);
996      if (t>max) max=t;
997      ll++;
998    }
999  }
1000  else
1001  {
1002    while ((p=pNext(p))!=NULL)
1003    {
1004      t=p_Totaldegree(p, r);
1005      if (t>max) max=t;
1006      ll++;
1007    }
1008  }
1009  *l=ll;
1010  return max;
1011}
1012
1013long pLDeg1c_Totaldegree(poly p,int *l, const ring r)
1014{
1015  p_CheckPolyRing(p, r);
1016  int ll=1;
1017  long  t,max;
1018
1019  max=p_Totaldegree(p, r);
1020  if (rIsSyzIndexRing(r))
1021  {
1022    long limit = rGetCurrSyzLimit(r);
1023    while ((p=pNext(p))!=NULL)
1024    {
1025      if (p_GetComp(p, r)<=limit)
1026      {
1027        if ((t=p_Totaldegree(p, r))>max) max=t;
1028        ll++;
1029      }
1030      else break;
1031    }
1032  }
1033  else
1034  {
1035    while ((p=pNext(p))!=NULL)
1036    {
1037      if ((t=p_Totaldegree(p, r))>max) max=t;
1038      ll++;
1039    }
1040  }
1041  *l=ll;
1042  return max;
1043}
1044
1045// like pLDeg1, only pFDeg == p_WFirstTotalDegree
1046long pLDeg1_WFirstTotalDegree(poly p,int *l, const ring r)
1047{
1048  p_CheckPolyRing(p, r);
1049  long k= p_GetComp(p, r);
1050  int ll=1;
1051  long  t,max;
1052
1053  max=p_WFirstTotalDegree(p, r);
1054  if (k > 0)
1055  {
1056    while (((p=pNext(p))!=NULL) && (p_GetComp(p, r)==k))
1057    {
1058      t=p_WFirstTotalDegree(p, r);
1059      if (t>max) max=t;
1060      ll++;
1061    }
1062  }
1063  else
1064  {
1065    while ((p=pNext(p))!=NULL)
1066    {
1067      t=p_WFirstTotalDegree(p, r);
1068      if (t>max) max=t;
1069      ll++;
1070    }
1071  }
1072  *l=ll;
1073  return max;
1074}
1075
1076long pLDeg1c_WFirstTotalDegree(poly p,int *l, const ring r)
1077{
1078  p_CheckPolyRing(p, r);
1079  int ll=1;
1080  long  t,max;
1081
1082  max=p_WFirstTotalDegree(p, r);
1083  if (rIsSyzIndexRing(r))
1084  {
1085    long limit = rGetCurrSyzLimit(r);
1086    while ((p=pNext(p))!=NULL)
1087    {
1088      if (p_GetComp(p, r)<=limit)
1089      {
1090        if ((t=p_Totaldegree(p, r))>max) max=t;
1091        ll++;
1092      }
1093      else break;
1094    }
1095  }
1096  else
1097  {
1098    while ((p=pNext(p))!=NULL)
1099    {
1100      if ((t=p_Totaldegree(p, r))>max) max=t;
1101      ll++;
1102    }
1103  }
1104  *l=ll;
1105  return max;
1106}
1107
1108/***************************************************************
1109 *
1110 * Maximal Exponent business
1111 *
1112 ***************************************************************/
1113
1114static inline unsigned long
1115p_GetMaxExpL2(unsigned long l1, unsigned long l2, const ring r,
1116              unsigned long number_of_exp)
1117{
1118  const unsigned long bitmask = r->bitmask;
1119  unsigned long ml1 = l1 & bitmask;
1120  unsigned long ml2 = l2 & bitmask;
1121  unsigned long max = (ml1 > ml2 ? ml1 : ml2);
1122  unsigned long j = number_of_exp - 1;
1123
1124  if (j > 0)
1125  {
1126    unsigned long mask = bitmask << r->BitsPerExp;
1127    while (1)
1128    {
1129      ml1 = l1 & mask;
1130      ml2 = l2 & mask;
1131      max |= ((ml1 > ml2 ? ml1 : ml2) & mask);
1132      j--;
1133      if (j == 0) break;
1134      mask = mask << r->BitsPerExp;
1135    }
1136  }
1137  return max;
1138}
1139
1140static inline unsigned long
1141p_GetMaxExpL2(unsigned long l1, unsigned long l2, const ring r)
1142{
1143  return p_GetMaxExpL2(l1, l2, r, r->ExpPerLong);
1144}
1145
1146poly p_GetMaxExpP(poly p, const ring r)
1147{
1148  p_CheckPolyRing(p, r);
1149  if (p == NULL) return p_Init(r);
1150  poly max = p_LmInit(p, r);
1151  pIter(p);
1152  if (p == NULL) return max;
1153  int i, offset;
1154  unsigned long l_p, l_max;
1155  unsigned long divmask = r->divmask;
1156
1157  do
1158  {
1159    offset = r->VarL_Offset[0];
1160    l_p = p->exp[offset];
1161    l_max = max->exp[offset];
1162    // do the divisibility trick to find out whether l has an exponent
1163    if (l_p > l_max ||
1164        (((l_max & divmask) ^ (l_p & divmask)) != ((l_max-l_p) & divmask)))
1165      max->exp[offset] = p_GetMaxExpL2(l_max, l_p, r);
1166
1167    for (i=1; i<r->VarL_Size; i++)
1168    {
1169      offset = r->VarL_Offset[i];
1170      l_p = p->exp[offset];
1171      l_max = max->exp[offset];
1172      // do the divisibility trick to find out whether l has an exponent
1173      if (l_p > l_max ||
1174          (((l_max & divmask) ^ (l_p & divmask)) != ((l_max-l_p) & divmask)))
1175        max->exp[offset] = p_GetMaxExpL2(l_max, l_p, r);
1176    }
1177    pIter(p);
1178  }
1179  while (p != NULL);
1180  return max;
1181}
1182
1183unsigned long p_GetMaxExpL(poly p, const ring r, unsigned long l_max)
1184{
1185  unsigned long l_p, divmask = r->divmask;
1186  int i;
1187
1188  while (p != NULL)
1189  {
1190    l_p = p->exp[r->VarL_Offset[0]];
1191    if (l_p > l_max ||
1192        (((l_max & divmask) ^ (l_p & divmask)) != ((l_max-l_p) & divmask)))
1193      l_max = p_GetMaxExpL2(l_max, l_p, r);
1194    for (i=1; i<r->VarL_Size; i++)
1195    {
1196      l_p = p->exp[r->VarL_Offset[i]];
1197      // do the divisibility trick to find out whether l has an exponent
1198      if (l_p > l_max ||
1199          (((l_max & divmask) ^ (l_p & divmask)) != ((l_max-l_p) & divmask)))
1200        l_max = p_GetMaxExpL2(l_max, l_p, r);
1201    }
1202    pIter(p);
1203  }
1204  return l_max;
1205}
1206
1207
1208
1209
1210/***************************************************************
1211 *
1212 * Misc things
1213 *
1214 ***************************************************************/
1215// returns TRUE, if all monoms have the same component
1216BOOLEAN p_OneComp(poly p, const ring r)
1217{
1218  if(p!=NULL)
1219  {
1220    long i = p_GetComp(p, r);
1221    while (pNext(p)!=NULL)
1222    {
1223      pIter(p);
1224      if(i != p_GetComp(p, r)) return FALSE;
1225    }
1226  }
1227  return TRUE;
1228}
1229
1230/*2
1231*test if a monomial /head term is a pure power
1232*/
1233int p_IsPurePower(const poly p, const ring r)
1234{
1235#ifdef HAVE_RINGS
1236  if (rField_is_Ring(r))
1237          {
1238          if (p == NULL) return 0;
1239          if (!n_IsUnit(pGetCoeff(p), r->cf)) return 0;
1240          }
1241#endif
1242  int i,k=0;
1243
1244  for (i=r->N;i;i--)
1245  {
1246    if (p_GetExp(p,i, r)!=0)
1247    {
1248      if(k!=0) return 0;
1249      k=i;
1250    }
1251  }
1252  return k;
1253}
1254
1255/*2
1256*test if a polynomial is univariate
1257* return -1 for constant,
1258* 0 for not univariate,s
1259* i if dep. on var(i)
1260*/
1261int p_IsUnivariate(poly p, const ring r)
1262{
1263  int i,k=-1;
1264
1265  while (p!=NULL)
1266  {
1267    for (i=r->N;i;i--)
1268    {
1269      if (p_GetExp(p,i, r)!=0)
1270      {
1271        if((k!=-1)&&(k!=i)) return 0;
1272        k=i;
1273      }
1274    }
1275    pIter(p);
1276  }
1277  return k;
1278}
1279
1280// set entry e[i] to 1 if var(i) occurs in p, ignore var(j) if e[j]>0
1281int  p_GetVariables(poly p, int * e, const ring r)
1282{
1283  int i;
1284  int n=0;
1285  while(p!=NULL)
1286  {
1287    n=0;
1288    for(i=r->N; i>0; i--)
1289    {
1290      if(e[i]==0)
1291      {
1292        if (p_GetExp(p,i,r)>0)
1293        {
1294          e[i]=1;
1295          n++;
1296        }
1297      }
1298      else
1299        n++;
1300    }
1301    if (n==r->N) break;
1302    pIter(p);
1303  }
1304  return n;
1305}
1306
1307
1308/*2
1309* returns a polynomial representing the integer i
1310*/
1311poly p_ISet(long i, const ring r)
1312{
1313  poly rc = NULL;
1314  if (i!=0)
1315  {
1316    rc = p_Init(r);
1317    pSetCoeff0(rc,n_Init(i,r->cf));
1318    if (n_IsZero(pGetCoeff(rc),r->cf))
1319      p_LmDelete(&rc,r);
1320  }
1321  return rc;
1322}
1323
1324/*2
1325* an optimized version of p_ISet for the special case 1
1326*/
1327poly p_One(const ring r)
1328{
1329  poly rc = p_Init(r);
1330  pSetCoeff0(rc,n_Init(1,r->cf));
1331  return rc;
1332}
1333
1334void p_Split(poly p, poly *h)
1335{
1336  *h=pNext(p);
1337  pNext(p)=NULL;
1338}
1339
1340/*2
1341* pair has no common factor ? or is no polynomial
1342*/
1343BOOLEAN p_HasNotCF(poly p1, poly p2, const ring r)
1344{
1345
1346  if (p_GetComp(p1,r) > 0 || p_GetComp(p2,r) > 0)
1347    return FALSE;
1348  int i = rVar(r);
1349  loop
1350  {
1351    if ((p_GetExp(p1, i, r) > 0) && (p_GetExp(p2, i, r) > 0))
1352      return FALSE;
1353    i--;
1354    if (i == 0)
1355      return TRUE;
1356  }
1357}
1358
1359/*2
1360* convert monomial given as string to poly, e.g. 1x3y5z
1361*/
1362const char * p_Read(const char *st, poly &rc, const ring r)
1363{
1364  if (r==NULL) { rc=NULL;return st;}
1365  int i,j;
1366  rc = p_Init(r);
1367  const char *s = r->cf->cfRead(st,&(rc->coef),r->cf);
1368  if (s==st)
1369  /* i.e. it does not start with a coeff: test if it is a ringvar*/
1370  {
1371    j = r_IsRingVar(s,r->names,r->N);
1372    if (j >= 0)
1373    {
1374      p_IncrExp(rc,1+j,r);
1375      while (*s!='\0') s++;
1376      goto done;
1377    }
1378  }
1379  while (*s!='\0')
1380  {
1381    char ss[2];
1382    ss[0] = *s++;
1383    ss[1] = '\0';
1384    j = r_IsRingVar(ss,r->names,r->N);
1385    if (j >= 0)
1386    {
1387      const char *s_save=s;
1388      s = eati(s,&i);
1389      if (((unsigned long)i) >  r->bitmask)
1390      {
1391        // exponent to large: it is not a monomial
1392        p_LmDelete(&rc,r);
1393        return s_save;
1394      }
1395      p_AddExp(rc,1+j, (long)i, r);
1396    }
1397    else
1398    {
1399      // 1st char of is not a varname
1400      // We return the parsed polynomial nevertheless. This is needed when
1401      // we are parsing coefficients in a rational function field.
1402      s--;
1403      break;
1404    }
1405  }
1406done:
1407  if (n_IsZero(pGetCoeff(rc),r->cf)) p_LmDelete(&rc,r);
1408  else
1409  {
1410#ifdef HAVE_PLURAL
1411    // in super-commutative ring
1412    // squares of anti-commutative variables are zeroes!
1413    if(rIsSCA(r))
1414    {
1415      const unsigned int iFirstAltVar = scaFirstAltVar(r);
1416      const unsigned int iLastAltVar  = scaLastAltVar(r);
1417
1418      assume(rc != NULL);
1419
1420      for(unsigned int k = iFirstAltVar; k <= iLastAltVar; k++)
1421        if( p_GetExp(rc, k, r) > 1 )
1422        {
1423          p_LmDelete(&rc, r);
1424          goto finish;
1425        }
1426    }
1427#endif
1428
1429    p_Setm(rc,r);
1430  }
1431finish:
1432  return s;
1433}
1434poly p_mInit(const char *st, BOOLEAN &ok, const ring r)
1435{
1436  poly p;
1437  const char *s=p_Read(st,p,r);
1438  if (*s!='\0')
1439  {
1440    if ((s!=st)&&isdigit(st[0]))
1441    {
1442      errorreported=TRUE;
1443    }
1444    ok=FALSE;
1445    p_Delete(&p,r);
1446    return NULL;
1447  }
1448  #ifdef PDEBUG
1449  _p_Test(p,r,PDEBUG);
1450  #endif
1451  ok=!errorreported;
1452  return p;
1453}
1454
1455/*2
1456* returns a polynomial representing the number n
1457* destroys n
1458*/
1459poly p_NSet(number n, const ring r)
1460{
1461  if (n_IsZero(n,r->cf))
1462  {
1463    n_Delete(&n, r->cf);
1464    return NULL;
1465  }
1466  else
1467  {
1468    poly rc = p_Init(r);
1469    pSetCoeff0(rc,n);
1470    return rc;
1471  }
1472}
1473/*2
1474* assumes that LM(a) = LM(b)*m, for some monomial m,
1475* returns the multiplicant m,
1476* leaves a and b unmodified
1477*/
1478poly p_Divide(poly a, poly b, const ring r)
1479{
1480  assume((p_GetComp(a,r)==p_GetComp(b,r)) || (p_GetComp(b,r)==0));
1481  int i;
1482  poly result = p_Init(r);
1483
1484  for(i=(int)r->N; i; i--)
1485    p_SetExp(result,i, p_GetExp(a,i,r)- p_GetExp(b,i,r),r);
1486  p_SetComp(result, p_GetComp(a,r) - p_GetComp(b,r),r);
1487  p_Setm(result,r);
1488  return result;
1489}
1490
1491poly p_Div_nn(poly p, const number n, const ring r)
1492{
1493  pAssume(!n_IsZero(n,r->cf));
1494  p_Test(p, r);
1495
1496  poly q = p;
1497  while (p != NULL)
1498  {
1499    number nc = pGetCoeff(p);
1500    pSetCoeff0(p, n_Div(nc, n, r->cf));
1501    n_Delete(&nc, r->cf);
1502    pIter(p);
1503  }
1504  p_Test(q, r);
1505  return q;
1506}
1507
1508/*2
1509* divides a by the monomial b, ignores monomials which are not divisible
1510* assumes that b is not NULL, destroyes b
1511*/
1512poly p_DivideM(poly a, poly b, const ring r)
1513{
1514  if (a==NULL) { p_Delete(&b,r); return NULL; }
1515  poly result=a;
1516  poly prev=NULL;
1517  int i;
1518#ifdef HAVE_RINGS
1519  number inv=pGetCoeff(b);
1520#else
1521  number inv=n_Invers(pGetCoeff(b),r->cf);
1522#endif
1523
1524  while (a!=NULL)
1525  {
1526    if (p_DivisibleBy(b,a,r))
1527    {
1528      for(i=(int)r->N; i; i--)
1529         p_SubExp(a,i, p_GetExp(b,i,r),r);
1530      p_SubComp(a, p_GetComp(b,r),r);
1531      p_Setm(a,r);
1532      prev=a;
1533      pIter(a);
1534    }
1535    else
1536    {
1537      if (prev==NULL)
1538      {
1539        p_LmDelete(&result,r);
1540        a=result;
1541      }
1542      else
1543      {
1544        p_LmDelete(&pNext(prev),r);
1545        a=pNext(prev);
1546      }
1547    }
1548  }
1549#ifdef HAVE_RINGS
1550  if (n_IsUnit(inv,r->cf))
1551  {
1552    inv = n_Invers(inv,r->cf);
1553    p_Mult_nn(result,inv,r);
1554    n_Delete(&inv, r->cf);
1555  }
1556  else
1557  {
1558    p_Div_nn(result,inv,r);
1559  }
1560#else
1561  p_Mult_nn(result,inv,r);
1562  n_Delete(&inv, r->cf);
1563#endif
1564  p_Delete(&b, r);
1565  return result;
1566}
1567
1568#ifdef HAVE_RINGS
1569/* TRUE iff LT(f) | LT(g) */
1570BOOLEAN p_DivisibleByRingCase(poly f, poly g, const ring r)
1571{
1572  int exponent;
1573  for(int i = (int)rVar(r); i>0; i--)
1574  {
1575    exponent = p_GetExp(g, i, r) - p_GetExp(f, i, r);
1576    if (exponent < 0) return FALSE;
1577  }
1578  return n_DivBy(pGetCoeff(g), pGetCoeff(f), r->cf);
1579}
1580#endif
1581
1582// returns the LCM of the head terms of a and b in *m
1583void p_Lcm(const poly a, const poly b, poly m, const ring r)
1584{
1585  for (int i=rVar(r); i; --i)
1586    p_SetExp(m,i, si_max( p_GetExp(a,i,r), p_GetExp(b,i,r)),r);
1587
1588  p_SetComp(m, si_max(p_GetComp(a,r), p_GetComp(b,r)),r);
1589  /* Don't do a pSetm here, otherwise hres/lres chockes */
1590}
1591
1592
1593
1594#ifdef HAVE_RATGRING
1595/*2
1596* returns the rational LCM of the head terms of a and b
1597* without coefficient!!!
1598*/
1599poly p_LcmRat(const poly a, const poly b, const long lCompM, const ring r)
1600{
1601  poly m = // p_One( r);
1602          p_Init(r);
1603
1604//  const int (currRing->N) = r->N;
1605
1606  //  for (int i = (currRing->N); i>=r->real_var_start; i--)
1607  for (int i = r->real_var_end; i>=r->real_var_start; i--)
1608  {
1609    const int lExpA = p_GetExp (a, i, r);
1610    const int lExpB = p_GetExp (b, i, r);
1611
1612    p_SetExp (m, i, si_max(lExpA, lExpB), r);
1613  }
1614
1615  p_SetComp (m, lCompM, r);
1616  p_Setm(m,r);
1617  n_New(&(p_GetCoeff(m, r)), r);
1618
1619  return(m);
1620};
1621
1622void p_LmDeleteAndNextRat(poly *p, int ishift, ring r)
1623{
1624  /* modifies p*/
1625  //  Print("start: "); Print(" "); p_wrp(*p,r);
1626  p_LmCheckPolyRing2(*p, r);
1627  poly q = p_Head(*p,r);
1628  const long cmp = p_GetComp(*p, r);
1629  while ( ( (*p)!=NULL ) && ( p_Comp_k_n(*p, q, ishift+1, r) ) && (p_GetComp(*p, r) == cmp) )
1630  {
1631    p_LmDelete(p,r);
1632    //    Print("while: ");p_wrp(*p,r);Print(" ");
1633  }
1634  //  p_wrp(*p,r);Print(" ");
1635  //  PrintS("end\n");
1636  p_LmDelete(&q,r);
1637}
1638
1639
1640/* returns x-coeff of p, i.e. a poly in x, s.t. corresponding xd-monomials
1641have the same D-part and the component 0
1642does not destroy p
1643*/
1644poly p_GetCoeffRat(poly p, int ishift, ring r)
1645{
1646  poly q   = pNext(p);
1647  poly res; // = p_Head(p,r);
1648  res = p_GetExp_k_n(p, ishift+1, r->N, r); // does pSetm internally
1649  p_SetCoeff(res,n_Copy(p_GetCoeff(p,r),r),r);
1650  poly s;
1651  long cmp = p_GetComp(p, r);
1652  while ( (q!= NULL) && (p_Comp_k_n(p, q, ishift+1, r)) && (p_GetComp(q, r) == cmp) )
1653  {
1654    s   = p_GetExp_k_n(q, ishift+1, r->N, r);
1655    p_SetCoeff(s,n_Copy(p_GetCoeff(q,r),r),r);
1656    res = p_Add_q(res,s,r);
1657    q   = pNext(q);
1658  }
1659  cmp = 0;
1660  p_SetCompP(res,cmp,r);
1661  return res;
1662}
1663
1664
1665
1666void p_ContentRat(poly &ph, const ring r)
1667// changes ph
1668// for rat coefficients in K(x1,..xN)
1669{
1670  // init array of RatLeadCoeffs
1671  //  poly p_GetCoeffRat(poly p, int ishift, ring r);
1672
1673  int len=pLength(ph);
1674  poly *C = (poly *)omAlloc0((len+1)*sizeof(poly));  //rat coeffs
1675  poly *LM = (poly *)omAlloc0((len+1)*sizeof(poly));  // rat lead terms
1676  int *D = (int *)omAlloc0((len+1)*sizeof(int));  //degrees of coeffs
1677  int *L = (int *)omAlloc0((len+1)*sizeof(int));  //lengths of coeffs
1678  int k = 0;
1679  poly p = p_Copy(ph, r); // ph will be needed below
1680  int mintdeg = p_Totaldegree(p, r);
1681  int minlen = len;
1682  int dd = 0; int i;
1683  int HasConstantCoef = 0;
1684  int is = r->real_var_start - 1;
1685  while (p!=NULL)
1686  {
1687    LM[k] = p_GetExp_k_n(p,1,is, r); // need LmRat istead of  p_HeadRat(p, is, currRing); !
1688    C[k] = p_GetCoeffRat(p, is, r);
1689    D[k] =  p_Totaldegree(C[k], r);
1690    mintdeg = si_min(mintdeg,D[k]);
1691    L[k] = pLength(C[k]);
1692    minlen = si_min(minlen,L[k]);
1693    if (p_IsConstant(C[k], r))
1694    {
1695      // C[k] = const, so the content will be numerical
1696      HasConstantCoef = 1;
1697      // smth like goto cleanup and return(pContent(p));
1698    }
1699    p_LmDeleteAndNextRat(&p, is, r);
1700    k++;
1701  }
1702
1703  // look for 1 element of minimal degree and of minimal length
1704  k--;
1705  poly d;
1706  int mindeglen = len;
1707  if (k<=0) // this poly is not a ratgring poly -> pContent
1708  {
1709    p_Delete(&C[0], r);
1710    p_Delete(&LM[0], r);
1711    p_Content(ph, r);
1712    goto cleanup;
1713  }
1714
1715  int pmindeglen;
1716  for(i=0; i<=k; i++)
1717  {
1718    if (D[i] == mintdeg)
1719    {
1720      if (L[i] < mindeglen)
1721      {
1722        mindeglen=L[i];
1723        pmindeglen = i;
1724      }
1725    }
1726  }
1727  d = p_Copy(C[pmindeglen], r);
1728  // there are dd>=1 mindeg elements
1729  // and pmideglen is the coordinate of one of the smallest among them
1730
1731  //  poly g = singclap_gcd(p_Copy(p,r),p_Copy(q,r));
1732  //  return naGcd(d,d2,currRing);
1733
1734  // adjoin pContentRat here?
1735  for(i=0; i<=k; i++)
1736  {
1737    d=singclap_gcd(d,p_Copy(C[i], r), r);
1738    if (p_Totaldegree(d, r)==0)
1739    {
1740      // cleanup, pContent, return
1741      p_Delete(&d, r);
1742      for(;k>=0;k--)
1743      {
1744        p_Delete(&C[k], r);
1745        p_Delete(&LM[k], r);
1746      }
1747      p_Content(ph, r);
1748      goto cleanup;
1749    }
1750  }
1751  for(i=0; i<=k; i++)
1752  {
1753    poly h=singclap_pdivide(C[i],d, r);
1754    p_Delete(&C[i], r);
1755    C[i]=h;
1756  }
1757
1758  // zusammensetzen,
1759  p=NULL; // just to be sure
1760  for(i=0; i<=k; i++)
1761  {
1762    p = p_Add_q(p, p_Mult_q(C[i],LM[i], r), r);
1763    C[i]=NULL; LM[i]=NULL;
1764  }
1765  p_Delete(&ph, r); // do not need it anymore
1766  ph = p;
1767  // aufraeumen, return
1768cleanup:
1769  omFree(C);
1770  omFree(LM);
1771  omFree(D);
1772  omFree(L);
1773}
1774
1775
1776#endif
1777
1778
1779/* assumes that p and divisor are univariate polynomials in r,
1780   mentioning the same variable;
1781   assumes divisor != NULL;
1782   p may be NULL;
1783   assumes a global monomial ordering in r;
1784   performs polynomial division of p by divisor:
1785     - afterwards p contains the remainder of the division, i.e.,
1786       p_before = result * divisor + p_afterwards;
1787     - if needResult == TRUE, then the method computes and returns 'result',
1788       otherwise NULL is returned (This parametrization can be used when
1789       one is only interested in the remainder of the division. In this
1790       case, the method will be slightly faster.)
1791   leaves divisor unmodified */
1792poly      p_PolyDiv(poly &p, const poly divisor, const BOOLEAN needResult, const ring r)
1793{
1794  assume(divisor != NULL);
1795  if (p == NULL) return NULL;
1796
1797  poly result = NULL;
1798  number divisorLC = p_GetCoeff(divisor, r);
1799  int divisorLE = p_GetExp(divisor, 1, r);
1800  while ((p != NULL) && (p_Deg(p, r) >= p_Deg(divisor, r)))
1801  {
1802    /* determine t = LT(p) / LT(divisor) */
1803    poly t = p_ISet(1, r);
1804    number c = n_Div(p_GetCoeff(p, r), divisorLC, r->cf);
1805    n_Normalize(c,r->cf);
1806    p_SetCoeff(t, c, r);
1807    int e = p_GetExp(p, 1, r) - divisorLE;
1808    p_SetExp(t, 1, e, r);
1809    p_Setm(t, r);
1810    if (needResult) result = p_Add_q(result, p_Copy(t, r), r);
1811    p = p_Add_q(p, p_Neg(p_Mult_q(t, p_Copy(divisor, r), r), r), r);
1812  }
1813  return result;
1814}
1815
1816/*2
1817* returns the partial differentiate of a by the k-th variable
1818* does not destroy the input
1819*/
1820poly p_Diff(poly a, int k, const ring r)
1821{
1822  poly res, f, last;
1823  number t;
1824
1825  last = res = NULL;
1826  while (a!=NULL)
1827  {
1828    if (p_GetExp(a,k,r)!=0)
1829    {
1830      f = p_LmInit(a,r);
1831      t = n_Init(p_GetExp(a,k,r),r->cf);
1832      pSetCoeff0(f,n_Mult(t,pGetCoeff(a),r->cf));
1833      n_Delete(&t,r->cf);
1834      if (n_IsZero(pGetCoeff(f),r->cf))
1835        p_LmDelete(&f,r);
1836      else
1837      {
1838        p_DecrExp(f,k,r);
1839        p_Setm(f,r);
1840        if (res==NULL)
1841        {
1842          res=last=f;
1843        }
1844        else
1845        {
1846          pNext(last)=f;
1847          last=f;
1848        }
1849      }
1850    }
1851    pIter(a);
1852  }
1853  return res;
1854}
1855
1856static poly p_DiffOpM(poly a, poly b,BOOLEAN multiply, const ring r)
1857{
1858  int i,j,s;
1859  number n,h,hh;
1860  poly p=p_One(r);
1861  n=n_Mult(pGetCoeff(a),pGetCoeff(b),r->cf);
1862  for(i=rVar(r);i>0;i--)
1863  {
1864    s=p_GetExp(b,i,r);
1865    if (s<p_GetExp(a,i,r))
1866    {
1867      n_Delete(&n,r->cf);
1868      p_LmDelete(&p,r);
1869      return NULL;
1870    }
1871    if (multiply)
1872    {
1873      for(j=p_GetExp(a,i,r); j>0;j--)
1874      {
1875        h = n_Init(s,r->cf);
1876        hh=n_Mult(n,h,r->cf);
1877        n_Delete(&h,r->cf);
1878        n_Delete(&n,r->cf);
1879        n=hh;
1880        s--;
1881      }
1882      p_SetExp(p,i,s,r);
1883    }
1884    else
1885    {
1886      p_SetExp(p,i,s-p_GetExp(a,i,r),r);
1887    }
1888  }
1889  p_Setm(p,r);
1890  /*if (multiply)*/ p_SetCoeff(p,n,r);
1891  if (n_IsZero(n,r->cf))  p=p_LmDeleteAndNext(p,r); // return NULL as p is a monomial
1892  return p;
1893}
1894
1895poly p_DiffOp(poly a, poly b,BOOLEAN multiply, const ring r)
1896{
1897  poly result=NULL;
1898  poly h;
1899  for(;a!=NULL;pIter(a))
1900  {
1901    for(h=b;h!=NULL;pIter(h))
1902    {
1903      result=p_Add_q(result,p_DiffOpM(a,h,multiply,r),r);
1904    }
1905  }
1906  return result;
1907}
1908/*2
1909* subtract p2 from p1, p1 and p2 are destroyed
1910* do not put attention on speed: the procedure is only used in the interpreter
1911*/
1912poly p_Sub(poly p1, poly p2, const ring r)
1913{
1914  return p_Add_q(p1, p_Neg(p2,r),r);
1915}
1916
1917/*3
1918* compute for a monomial m
1919* the power m^exp, exp > 1
1920* destroys p
1921*/
1922static poly p_MonPower(poly p, int exp, const ring r)
1923{
1924  int i;
1925
1926  if(!n_IsOne(pGetCoeff(p),r->cf))
1927  {
1928    number x, y;
1929    y = pGetCoeff(p);
1930    n_Power(y,exp,&x,r->cf);
1931    n_Delete(&y,r->cf);
1932    pSetCoeff0(p,x);
1933  }
1934  for (i=rVar(r); i!=0; i--)
1935  {
1936    p_MultExp(p,i, exp,r);
1937  }
1938  p_Setm(p,r);
1939  return p;
1940}
1941
1942/*3
1943* compute for monomials p*q
1944* destroys p, keeps q
1945*/
1946static void p_MonMult(poly p, poly q, const ring r)
1947{
1948  number x, y;
1949
1950  y = pGetCoeff(p);
1951  x = n_Mult(y,pGetCoeff(q),r->cf);
1952  n_Delete(&y,r->cf);
1953  pSetCoeff0(p,x);
1954  //for (int i=pVariables; i!=0; i--)
1955  //{
1956  //  pAddExp(p,i, pGetExp(q,i));
1957  //}
1958  //p->Order += q->Order;
1959  p_ExpVectorAdd(p,q,r);
1960}
1961
1962/*3
1963* compute for monomials p*q
1964* keeps p, q
1965*/
1966static poly p_MonMultC(poly p, poly q, const ring rr)
1967{
1968  number x;
1969  poly r = p_Init(rr);
1970
1971  x = n_Mult(pGetCoeff(p),pGetCoeff(q),rr->cf);
1972  pSetCoeff0(r,x);
1973  p_ExpVectorSum(r,p, q, rr);
1974  return r;
1975}
1976
1977/*3
1978*  create binomial coef.
1979*/
1980static number* pnBin(int exp, const ring r)
1981{
1982  int e, i, h;
1983  number x, y, *bin=NULL;
1984
1985  x = n_Init(exp,r->cf);
1986  if (n_IsZero(x,r->cf))
1987  {
1988    n_Delete(&x,r->cf);
1989    return bin;
1990  }
1991  h = (exp >> 1) + 1;
1992  bin = (number *)omAlloc0(h*sizeof(number));
1993  bin[1] = x;
1994  if (exp < 4)
1995    return bin;
1996  i = exp - 1;
1997  for (e=2; e<h; e++)
1998  {
1999      x = n_Init(i,r->cf);
2000      i--;
2001      y = n_Mult(x,bin[e-1],r->cf);
2002      n_Delete(&x,r->cf);
2003      x = n_Init(e,r->cf);
2004      bin[e] = n_ExactDiv(y,x,r->cf);
2005      n_Delete(&x,r->cf);
2006      n_Delete(&y,r->cf);
2007  }
2008  return bin;
2009}
2010
2011static void pnFreeBin(number *bin, int exp,const coeffs r)
2012{
2013  int e, h = (exp >> 1) + 1;
2014
2015  if (bin[1] != NULL)
2016  {
2017    for (e=1; e<h; e++)
2018      n_Delete(&(bin[e]),r);
2019  }
2020  omFreeSize((ADDRESS)bin, h*sizeof(number));
2021}
2022
2023/*
2024*  compute for a poly p = head+tail, tail is monomial
2025*          (head + tail)^exp, exp > 1
2026*          with binomial coef.
2027*/
2028static poly p_TwoMonPower(poly p, int exp, const ring r)
2029{
2030  int eh, e;
2031  long al;
2032  poly *a;
2033  poly tail, b, res, h;
2034  number x;
2035  number *bin = pnBin(exp,r);
2036
2037  tail = pNext(p);
2038  if (bin == NULL)
2039  {
2040    p_MonPower(p,exp,r);
2041    p_MonPower(tail,exp,r);
2042#ifdef PDEBUG
2043    p_Test(p,r);
2044#endif
2045    return p;
2046  }
2047  eh = exp >> 1;
2048  al = (exp + 1) * sizeof(poly);
2049  a = (poly *)omAlloc(al);
2050  a[1] = p;
2051  for (e=1; e<exp; e++)
2052  {
2053    a[e+1] = p_MonMultC(a[e],p,r);
2054  }
2055  res = a[exp];
2056  b = p_Head(tail,r);
2057  for (e=exp-1; e>eh; e--)
2058  {
2059    h = a[e];
2060    x = n_Mult(bin[exp-e],pGetCoeff(h),r->cf);
2061    p_SetCoeff(h,x,r);
2062    p_MonMult(h,b,r);
2063    res = pNext(res) = h;
2064    p_MonMult(b,tail,r);
2065  }
2066  for (e=eh; e!=0; e--)
2067  {
2068    h = a[e];
2069    x = n_Mult(bin[e],pGetCoeff(h),r->cf);
2070    p_SetCoeff(h,x,r);
2071    p_MonMult(h,b,r);
2072    res = pNext(res) = h;
2073    p_MonMult(b,tail,r);
2074  }
2075  p_LmDelete(&tail,r);
2076  pNext(res) = b;
2077  pNext(b) = NULL;
2078  res = a[exp];
2079  omFreeSize((ADDRESS)a, al);
2080  pnFreeBin(bin, exp, r->cf);
2081//  tail=res;
2082// while((tail!=NULL)&&(pNext(tail)!=NULL))
2083// {
2084//   if(nIsZero(pGetCoeff(pNext(tail))))
2085//   {
2086//     pLmDelete(&pNext(tail));
2087//   }
2088//   else
2089//     pIter(tail);
2090// }
2091#ifdef PDEBUG
2092  p_Test(res,r);
2093#endif
2094  return res;
2095}
2096
2097static poly p_Pow(poly p, int i, const ring r)
2098{
2099  poly rc = p_Copy(p,r);
2100  i -= 2;
2101  do
2102  {
2103    rc = p_Mult_q(rc,p_Copy(p,r),r);
2104    p_Normalize(rc,r);
2105    i--;
2106  }
2107  while (i != 0);
2108  return p_Mult_q(rc,p,r);
2109}
2110
2111/*2
2112* returns the i-th power of p
2113* p will be destroyed
2114*/
2115poly p_Power(poly p, int i, const ring r)
2116{
2117  poly rc=NULL;
2118
2119  if (i==0)
2120  {
2121    p_Delete(&p,r);
2122    return p_One(r);
2123  }
2124
2125  if(p!=NULL)
2126  {
2127    if ( (i > 0) && ((unsigned long ) i > (r->bitmask)))
2128    {
2129      Werror("exponent %d is too large, max. is %ld",i,r->bitmask);
2130      return NULL;
2131    }
2132    switch (i)
2133    {
2134// cannot happen, see above
2135//      case 0:
2136//      {
2137//        rc=pOne();
2138//        pDelete(&p);
2139//        break;
2140//      }
2141      case 1:
2142        rc=p;
2143        break;
2144      case 2:
2145        rc=p_Mult_q(p_Copy(p,r),p,r);
2146        break;
2147      default:
2148        if (i < 0)
2149        {
2150          p_Delete(&p,r);
2151          return NULL;
2152        }
2153        else
2154        {
2155#ifdef HAVE_PLURAL
2156          if (rIsPluralRing(r)) /* in the NC case nothing helps :-( */
2157          {
2158            int j=i;
2159            rc = p_Copy(p,r);
2160            while (j>1)
2161            {
2162              rc = p_Mult_q(p_Copy(p,r),rc,r);
2163              j--;
2164            }
2165            p_Delete(&p,r);
2166            return rc;
2167          }
2168#endif
2169          rc = pNext(p);
2170          if (rc == NULL)
2171            return p_MonPower(p,i,r);
2172          /* else: binom ?*/
2173          int char_p=rChar(r);
2174          if ((pNext(rc) != NULL)
2175#ifdef HAVE_RINGS
2176             || rField_is_Ring(r)
2177#endif
2178             )
2179            return p_Pow(p,i,r);
2180          if ((char_p==0) || (i<=char_p))
2181            return p_TwoMonPower(p,i,r);
2182          return p_Pow(p,i,r);
2183        }
2184      /*end default:*/
2185    }
2186  }
2187  return rc;
2188}
2189
2190/* --------------------------------------------------------------------------------*/
2191/* content suff                                                                   */
2192
2193static number p_InitContent(poly ph, const ring r);
2194
2195#define CLEARENUMERATORS 1
2196
2197void p_Content(poly ph, const ring r)
2198{
2199  assume( ph != NULL );
2200
2201  assume( r != NULL ); assume( r->cf != NULL );
2202
2203
2204#if CLEARENUMERATORS
2205  if( 0 )
2206  {
2207    const coeffs C = r->cf;
2208      // experimentall (recursive enumerator treatment) of alg. Ext!
2209    CPolyCoeffsEnumerator itr(ph);
2210    n_ClearContent(itr, r->cf);
2211
2212    p_Test(ph, r); n_Test(pGetCoeff(ph), C);
2213    assume(n_GreaterZero(pGetCoeff(ph), C)); // ??
2214
2215      // if(!n_GreaterZero(pGetCoeff(ph),r->cf)) ph = p_Neg(ph,r);
2216    return;
2217  }
2218#endif
2219
2220
2221#ifdef HAVE_RINGS
2222  if (rField_is_Ring(r))
2223  {
2224    if (rField_has_Units(r))
2225    {
2226      number k = n_GetUnit(pGetCoeff(ph),r->cf);
2227      if (!n_IsOne(k,r->cf))
2228      {
2229        number tmpGMP = k;
2230        k = n_Invers(k,r->cf);
2231        n_Delete(&tmpGMP,r->cf);
2232        poly h = pNext(ph);
2233        p_SetCoeff(ph, n_Mult(pGetCoeff(ph), k,r->cf),r);
2234        while (h != NULL)
2235        {
2236          p_SetCoeff(h, n_Mult(pGetCoeff(h), k,r->cf),r);
2237          pIter(h);
2238        }
2239//        assume( n_GreaterZero(pGetCoeff(ph),r->cf) );
2240//        if(!n_GreaterZero(pGetCoeff(ph),r->cf)) ph = p_Neg(ph,r);
2241      }
2242      n_Delete(&k,r->cf);
2243    }
2244    return;
2245  }
2246#endif
2247  number h,d;
2248  poly p;
2249
2250  if(TEST_OPT_CONTENTSB) return;
2251  if(pNext(ph)==NULL)
2252  {
2253    p_SetCoeff(ph,n_Init(1,r->cf),r);
2254  }
2255  else
2256  {
2257    assume( pNext(ph) != NULL );
2258#if CLEARENUMERATORS
2259    if( nCoeff_is_Q(r->cf) )
2260    {
2261      // experimentall (recursive enumerator treatment) of alg. Ext!
2262      CPolyCoeffsEnumerator itr(ph);
2263      n_ClearContent(itr, r->cf);
2264
2265      p_Test(ph, r); n_Test(pGetCoeff(ph), r->cf);
2266      assume(n_GreaterZero(pGetCoeff(ph), r->cf)); // ??
2267
2268      // if(!n_GreaterZero(pGetCoeff(ph),r->cf)) ph = p_Neg(ph,r);
2269      return;
2270    }
2271#endif
2272
2273    n_Normalize(pGetCoeff(ph),r->cf);
2274    if(!n_GreaterZero(pGetCoeff(ph),r->cf)) ph = p_Neg(ph,r);
2275    if (rField_is_Q(r)) // should not be used anymore if CLEARENUMERATORS is 1
2276    {
2277      h=p_InitContent(ph,r);
2278      p=ph;
2279    }
2280    else
2281    {
2282      h=n_Copy(pGetCoeff(ph),r->cf);
2283      p = pNext(ph);
2284    }
2285    while (p!=NULL)
2286    {
2287      n_Normalize(pGetCoeff(p),r->cf);
2288      d=n_SubringGcd(h,pGetCoeff(p),r->cf);
2289      n_Delete(&h,r->cf);
2290      h = d;
2291      if(n_IsOne(h,r->cf))
2292      {
2293        break;
2294      }
2295      pIter(p);
2296    }
2297    p = ph;
2298    //number tmp;
2299    if(!n_IsOne(h,r->cf))
2300    {
2301      while (p!=NULL)
2302      {
2303        //d = nDiv(pGetCoeff(p),h);
2304        //tmp = nExactDiv(pGetCoeff(p),h);
2305        //if (!nEqual(d,tmp))
2306        //{
2307        //  StringSetS("** div0:");nWrite(pGetCoeff(p));StringAppendS("/");
2308        //  nWrite(h);StringAppendS("=");nWrite(d);StringAppendS(" int:");
2309        //  nWrite(tmp);Print(StringEndS("\n")); // NOTE/TODO: use StringAppendS("\n"); omFree(s);
2310        //}
2311        //nDelete(&tmp);
2312        d = n_ExactDiv(pGetCoeff(p),h,r->cf);
2313        p_SetCoeff(p,d,r);
2314        pIter(p);
2315      }
2316    }
2317    n_Delete(&h,r->cf);
2318    if (rField_is_Q_a(r))
2319    {
2320      // special handling for alg. ext.:
2321      if (getCoeffType(r->cf)==n_algExt)
2322      {
2323        h = n_Init(1, r->cf->extRing->cf);
2324        p=ph;
2325        while (p!=NULL)
2326        { // each monom: coeff in Q_a
2327          poly c_n_n=(poly)pGetCoeff(p);
2328          poly c_n=c_n_n;
2329          while (c_n!=NULL)
2330          { // each monom: coeff in Q
2331            d=n_NormalizeHelper(h,pGetCoeff(c_n),r->cf->extRing->cf);
2332            n_Delete(&h,r->cf->extRing->cf);
2333            h=d;
2334            pIter(c_n);
2335          }
2336          pIter(p);
2337        }
2338        /* h contains the 1/lcm of all denominators in c_n_n*/
2339        //n_Normalize(h,r->cf->extRing->cf);
2340        if(!n_IsOne(h,r->cf->extRing->cf))
2341        {
2342          p=ph;
2343          while (p!=NULL)
2344          { // each monom: coeff in Q_a
2345            poly c_n=(poly)pGetCoeff(p);
2346            while (c_n!=NULL)
2347            { // each monom: coeff in Q
2348              d=n_Mult(h,pGetCoeff(c_n),r->cf->extRing->cf);
2349              n_Normalize(d,r->cf->extRing->cf);
2350              n_Delete(&pGetCoeff(c_n),r->cf->extRing->cf);
2351              pGetCoeff(c_n)=d;
2352              pIter(c_n);
2353            }
2354            pIter(p);
2355          }
2356        }
2357        n_Delete(&h,r->cf->extRing->cf);
2358      }
2359      /*else
2360      {
2361      // special handling for rat. functions.:
2362        number hzz =NULL;
2363        p=ph;
2364        while (p!=NULL)
2365        { // each monom: coeff in Q_a (Z_a)
2366          fraction f=(fraction)pGetCoeff(p);
2367          poly c_n=NUM(f);
2368          if (hzz==NULL)
2369          {
2370            hzz=n_Copy(pGetCoeff(c_n),r->cf->extRing->cf);
2371            pIter(c_n);
2372          }
2373          while ((c_n!=NULL)&&(!n_IsOne(hzz,r->cf->extRing->cf)))
2374          { // each monom: coeff in Q (Z)
2375            d=n_Gcd(hzz,pGetCoeff(c_n),r->cf->extRing->cf);
2376            n_Delete(&hzz,r->cf->extRing->cf);
2377            hzz=d;
2378            pIter(c_n);
2379          }
2380          pIter(p);
2381        }
2382        // hzz contains the gcd of all numerators in f
2383        h=n_Invers(hzz,r->cf->extRing->cf);
2384        n_Delete(&hzz,r->cf->extRing->cf);
2385        n_Normalize(h,r->cf->extRing->cf);
2386        if(!n_IsOne(h,r->cf->extRing->cf))
2387        {
2388          p=ph;
2389          while (p!=NULL)
2390          { // each monom: coeff in Q_a (Z_a)
2391            fraction f=(fraction)pGetCoeff(p);
2392            NUM(f)=p_Mult_nn(NUM(f),h,r->cf->extRing);
2393            p_Normalize(NUM(f),r->cf->extRing);
2394            pIter(p);
2395          }
2396        }
2397        n_Delete(&h,r->cf->extRing->cf);
2398      }*/
2399    }
2400  }
2401  if(!n_GreaterZero(pGetCoeff(ph),r->cf)) ph = p_Neg(ph,r);
2402}
2403
2404// Not yet?
2405#if 1 // currently only used by Singular/janet
2406void p_SimpleContent(poly ph, int smax, const ring r)
2407{
2408  if(TEST_OPT_CONTENTSB) return;
2409  if (ph==NULL) return;
2410  if (pNext(ph)==NULL)
2411  {
2412    p_SetCoeff(ph,n_Init(1,r->cf),r);
2413    return;
2414  }
2415  if ((pNext(pNext(ph))==NULL)||(!rField_is_Q(r)))
2416  {
2417    return;
2418  }
2419  number d=p_InitContent(ph,r);
2420  if (n_Size(d,r->cf)<=smax)
2421  {
2422    //if (TEST_OPT_PROT) PrintS("G");
2423    return;
2424  }
2425
2426
2427  poly p=ph;
2428  number h=d;
2429  if (smax==1) smax=2;
2430  while (p!=NULL)
2431  {
2432#if 0
2433    d=nlGcd(h,pGetCoeff(p),r->cf);
2434    nlDelete(&h,r->cf);
2435    h = d;
2436#else
2437    nlInpGcd(h,pGetCoeff(p),r->cf);
2438#endif
2439    if(nlSize(h,r->cf)<smax)
2440    {
2441      //if (TEST_OPT_PROT) PrintS("g");
2442      return;
2443    }
2444    pIter(p);
2445  }
2446  p = ph;
2447  if (!nlGreaterZero(pGetCoeff(p),r->cf)) h=nlNeg(h,r->cf);
2448  if(nlIsOne(h,r->cf)) return;
2449  //if (TEST_OPT_PROT) PrintS("c");
2450  while (p!=NULL)
2451  {
2452#if 1
2453    d = nlExactDiv(pGetCoeff(p),h,r->cf);
2454    p_SetCoeff(p,d,r);
2455#else
2456    nlInpExactDiv(pGetCoeff(p),h,r->cf);
2457#endif
2458    pIter(p);
2459  }
2460  nlDelete(&h,r->cf);
2461}
2462#endif
2463
2464static number p_InitContent(poly ph, const ring r)
2465// only for coefficients in Q
2466#if 0
2467{
2468  assume(!TEST_OPT_CONTENTSB);
2469  assume(ph!=NULL);
2470  assume(pNext(ph)!=NULL);
2471  assume(rField_is_Q(r));
2472  if (pNext(pNext(ph))==NULL)
2473  {
2474    return nlGetNom(pGetCoeff(pNext(ph)),r->cf);
2475  }
2476  poly p=ph;
2477  number n1=nlGetNom(pGetCoeff(p),r->cf);
2478  pIter(p);
2479  number n2=nlGetNom(pGetCoeff(p),r->cf);
2480  pIter(p);
2481  number d;
2482  number t;
2483  loop
2484  {
2485    nlNormalize(pGetCoeff(p),r->cf);
2486    t=nlGetNom(pGetCoeff(p),r->cf);
2487    if (nlGreaterZero(t,r->cf))
2488      d=nlAdd(n1,t,r->cf);
2489    else
2490      d=nlSub(n1,t,r->cf);
2491    nlDelete(&t,r->cf);
2492    nlDelete(&n1,r->cf);
2493    n1=d;
2494    pIter(p);
2495    if (p==NULL) break;
2496    nlNormalize(pGetCoeff(p),r->cf);
2497    t=nlGetNom(pGetCoeff(p),r->cf);
2498    if (nlGreaterZero(t,r->cf))
2499      d=nlAdd(n2,t,r->cf);
2500    else
2501      d=nlSub(n2,t,r->cf);
2502    nlDelete(&t,r->cf);
2503    nlDelete(&n2,r->cf);
2504    n2=d;
2505    pIter(p);
2506    if (p==NULL) break;
2507  }
2508  d=nlGcd(n1,n2,r->cf);
2509  nlDelete(&n1,r->cf);
2510  nlDelete(&n2,r->cf);
2511  return d;
2512}
2513#else
2514{
2515  number d=pGetCoeff(ph);
2516  if(SR_HDL(d)&SR_INT) return d;
2517  int s=mpz_size1(d->z);
2518  int s2=-1;
2519  number d2;
2520  loop
2521  {
2522    pIter(ph);
2523    if(ph==NULL)
2524    {
2525      if (s2==-1) return nlCopy(d,r->cf);
2526      break;
2527    }
2528    if (SR_HDL(pGetCoeff(ph))&SR_INT)
2529    {
2530      s2=s;
2531      d2=d;
2532      s=0;
2533      d=pGetCoeff(ph);
2534      if (s2==0) break;
2535    }
2536    else
2537    if (mpz_size1((pGetCoeff(ph)->z))<=s)
2538    {
2539      s2=s;
2540      d2=d;
2541      d=pGetCoeff(ph);
2542      s=mpz_size1(d->z);
2543    }
2544  }
2545  return nlGcd(d,d2,r->cf);
2546}
2547#endif
2548
2549//void pContent(poly ph)
2550//{
2551//  number h,d;
2552//  poly p;
2553//
2554//  p = ph;
2555//  if(pNext(p)==NULL)
2556//  {
2557//    pSetCoeff(p,nInit(1));
2558//  }
2559//  else
2560//  {
2561//#ifdef PDEBUG
2562//    if (!pTest(p)) return;
2563//#endif
2564//    nNormalize(pGetCoeff(p));
2565//    if(!nGreaterZero(pGetCoeff(ph)))
2566//    {
2567//      ph = pNeg(ph);
2568//      nNormalize(pGetCoeff(p));
2569//    }
2570//    h=pGetCoeff(p);
2571//    pIter(p);
2572//    while (p!=NULL)
2573//    {
2574//      nNormalize(pGetCoeff(p));
2575//      if (nGreater(h,pGetCoeff(p))) h=pGetCoeff(p);
2576//      pIter(p);
2577//    }
2578//    h=nCopy(h);
2579//    p=ph;
2580//    while (p!=NULL)
2581//    {
2582//      d=n_Gcd(h,pGetCoeff(p));
2583//      nDelete(&h);
2584//      h = d;
2585//      if(nIsOne(h))
2586//      {
2587//        break;
2588//      }
2589//      pIter(p);
2590//    }
2591//    p = ph;
2592//    //number tmp;
2593//    if(!nIsOne(h))
2594//    {
2595//      while (p!=NULL)
2596//      {
2597//        d = nExactDiv(pGetCoeff(p),h);
2598//        pSetCoeff(p,d);
2599//        pIter(p);
2600//      }
2601//    }
2602//    nDelete(&h);
2603//    if ( (nGetChar() == 1) || (nGetChar() < 0) ) /* Q[a],Q(a),Zp[a],Z/p(a) */
2604//    {
2605//      pTest(ph);
2606//      singclap_divide_content(ph);
2607//      pTest(ph);
2608//    }
2609//  }
2610//}
2611#if 0
2612void p_Content(poly ph, const ring r)
2613{
2614  number h,d;
2615  poly p;
2616
2617  if(pNext(ph)==NULL)
2618  {
2619    p_SetCoeff(ph,n_Init(1,r->cf),r);
2620  }
2621  else
2622  {
2623    n_Normalize(pGetCoeff(ph),r->cf);
2624    if(!n_GreaterZero(pGetCoeff(ph),r->cf)) ph = p_Neg(ph,r);
2625    h=n_Copy(pGetCoeff(ph),r->cf);
2626    p = pNext(ph);
2627    while (p!=NULL)
2628    {
2629      n_Normalize(pGetCoeff(p),r->cf);
2630      d=n_Gcd(h,pGetCoeff(p),r->cf);
2631      n_Delete(&h,r->cf);
2632      h = d;
2633      if(n_IsOne(h,r->cf))
2634      {
2635        break;
2636      }
2637      pIter(p);
2638    }
2639    p = ph;
2640    //number tmp;
2641    if(!n_IsOne(h,r->cf))
2642    {
2643      while (p!=NULL)
2644      {
2645        //d = nDiv(pGetCoeff(p),h);
2646        //tmp = nExactDiv(pGetCoeff(p),h);
2647        //if (!nEqual(d,tmp))
2648        //{
2649        //  StringSetS("** div0:");nWrite(pGetCoeff(p));StringAppendS("/");
2650        //  nWrite(h);StringAppendS("=");nWrite(d);StringAppendS(" int:");
2651        //  nWrite(tmp);Print(StringEndS("\n")); // NOTE/TODO: use StringAppendS("\n"); omFree(s);
2652        //}
2653        //nDelete(&tmp);
2654        d = n_ExactDiv(pGetCoeff(p),h,r->cf);
2655        p_SetCoeff(p,d,r->cf);
2656        pIter(p);
2657      }
2658    }
2659    n_Delete(&h,r->cf);
2660    //if ( (n_GetChar(r) == 1) || (n_GetChar(r) < 0) ) /* Q[a],Q(a),Zp[a],Z/p(a) */
2661    //{
2662    //  singclap_divide_content(ph);
2663    //  if(!n_GreaterZero(pGetCoeff(ph),r)) ph = p_Neg(ph,r);
2664    //}
2665  }
2666}
2667#endif
2668/* ---------------------------------------------------------------------------*/
2669/* cleardenom suff                                                           */
2670poly p_Cleardenom(poly p, const ring r)
2671{
2672  if( p == NULL )
2673    return NULL;
2674
2675  assume( r != NULL ); assume( r->cf != NULL ); const coeffs C = r->cf;
2676
2677#if CLEARENUMERATORS
2678  if( 0 )
2679  {
2680    CPolyCoeffsEnumerator itr(p);
2681
2682    n_ClearDenominators(itr, C);
2683
2684    n_ClearContent(itr, C); // divide out the content
2685
2686    p_Test(p, r); n_Test(pGetCoeff(p), C);
2687    assume(n_GreaterZero(pGetCoeff(p), C)); // ??
2688//    if(!n_GreaterZero(pGetCoeff(p),C)) p = p_Neg(p,r);
2689
2690    return p;
2691  }
2692#endif
2693
2694
2695  number d, h;
2696
2697#ifdef HAVE_RINGS
2698  if (rField_is_Ring(r))
2699  {
2700    p_Content(p,r);
2701    if(!n_GreaterZero(pGetCoeff(p),C)) p = p_Neg(p,r);
2702    return p;
2703  }
2704#endif
2705
2706  if (rField_is_Zp(r) && TEST_OPT_INTSTRATEGY)
2707  {
2708    if(!n_GreaterZero(pGetCoeff(p),C)) p = p_Neg(p,r);
2709    return p;
2710  }
2711
2712  assume(p != NULL);
2713
2714  if(pNext(p)==NULL)
2715  {
2716    /*
2717    if (TEST_OPT_CONTENTSB)
2718    {
2719      number n=n_GetDenom(pGetCoeff(p),r->cf);
2720      if (!n_IsOne(n,r->cf))
2721      {
2722        number nn=n_Mult(pGetCoeff(p),n,r->cf);
2723        n_Normalize(nn,r->cf);
2724        p_SetCoeff(p,nn,r);
2725      }
2726      n_Delete(&n,r->cf);
2727    }
2728    else
2729    */
2730      p_SetCoeff(p,n_Init(1,r->cf),r);
2731
2732    /*assume( n_GreaterZero(pGetCoeff(p),C) );
2733    if(!n_GreaterZero(pGetCoeff(p),C)) p = p_Neg(p,r);
2734    */
2735    return p;
2736  }
2737
2738  assume(pNext(p)!=NULL);
2739  poly start=p;
2740
2741#if 0 && CLEARENUMERATORS
2742//CF: does not seem to work that well..
2743
2744  if( nCoeff_is_Q(C) || nCoeff_is_Q_a(C) )
2745  {
2746    CPolyCoeffsEnumerator itr(p);
2747
2748    n_ClearDenominators(itr, C);
2749
2750    n_ClearContent(itr, C); // divide out the content
2751
2752    p_Test(p, r); n_Test(pGetCoeff(p), C);
2753    assume(n_GreaterZero(pGetCoeff(p), C)); // ??
2754//    if(!n_GreaterZero(pGetCoeff(p),C)) p = p_Neg(p,r);
2755
2756    return start;
2757  }
2758#endif
2759
2760  if(1)
2761  {
2762    h = n_Init(1,r->cf);
2763    while (p!=NULL)
2764    {
2765      n_Normalize(pGetCoeff(p),r->cf);
2766      d=n_NormalizeHelper(h,pGetCoeff(p),r->cf);
2767      n_Delete(&h,r->cf);
2768      h=d;
2769      pIter(p);
2770    }
2771    /* contains the 1/lcm of all denominators */
2772    if(!n_IsOne(h,r->cf))
2773    {
2774      p = start;
2775      while (p!=NULL)
2776      {
2777        /* should be:
2778        * number hh;
2779        * nGetDenom(p->coef,&hh);
2780        * nMult(&h,&hh,&d);
2781        * nNormalize(d);
2782        * nDelete(&hh);
2783        * nMult(d,p->coef,&hh);
2784        * nDelete(&d);
2785        * nDelete(&(p->coef));
2786        * p->coef =hh;
2787        */
2788        d=n_Mult(h,pGetCoeff(p),r->cf);
2789        n_Normalize(d,r->cf);
2790        p_SetCoeff(p,d,r);
2791        pIter(p);
2792      }
2793      n_Delete(&h,r->cf);
2794    }
2795    n_Delete(&h,r->cf);
2796    p=start;
2797
2798    p_Content(p,r);
2799#ifdef HAVE_RATGRING
2800    if (rIsRatGRing(r))
2801    {
2802      /* quick unit detection in the rational case is done in gr_nc_bba */
2803      p_ContentRat(p, r);
2804      start=p;
2805    }
2806#endif
2807  }
2808
2809  if(!n_GreaterZero(pGetCoeff(p),C)) p = p_Neg(p,r);
2810
2811  return start;
2812}
2813
2814void p_Cleardenom_n(poly ph,const ring r,number &c)
2815{
2816  const coeffs C = r->cf;
2817  number d, h;
2818
2819  assume( ph != NULL );
2820
2821  poly p = ph;
2822
2823#if CLEARENUMERATORS
2824  if( 0 )
2825  {
2826    CPolyCoeffsEnumerator itr(ph);
2827
2828    n_ClearDenominators(itr, d, C); // multiply with common denom. d
2829    n_ClearContent(itr, h, C); // divide by the content h
2830
2831    c = n_Div(d, h, C); // d/h
2832
2833    n_Delete(&d, C);
2834    n_Delete(&h, C);
2835
2836    n_Test(c, C);
2837
2838    p_Test(ph, r); n_Test(pGetCoeff(ph), C);
2839    assume(n_GreaterZero(pGetCoeff(ph), C)); // ??
2840/*
2841    if(!n_GreaterZero(pGetCoeff(ph),C))
2842    {
2843      ph = p_Neg(ph,r);
2844      c = n_InpNeg(c, C);
2845    }
2846*/
2847    return;
2848  }
2849#endif
2850
2851
2852  if( pNext(p) == NULL )
2853  {
2854    c=n_Invers(pGetCoeff(p), C);
2855    p_SetCoeff(p, n_Init(1, C), r);
2856
2857    assume( n_GreaterZero(pGetCoeff(ph),C) );
2858    if(!n_GreaterZero(pGetCoeff(ph),C))
2859    {
2860      ph = p_Neg(ph,r);
2861      c = n_InpNeg(c, C);
2862    }
2863
2864    return;
2865  }
2866
2867  assume( pNext(p) != NULL );
2868
2869#if CLEARENUMERATORS
2870  if( nCoeff_is_Q(C) || nCoeff_is_Q_a(C) )
2871  {
2872    CPolyCoeffsEnumerator itr(ph);
2873
2874    n_ClearDenominators(itr, d, C); // multiply with common denom. d
2875    n_ClearContent(itr, h, C); // divide by the content h
2876
2877    c = n_Div(d, h, C); // d/h
2878
2879    n_Delete(&d, C);
2880    n_Delete(&h, C);
2881
2882    n_Test(c, C);
2883
2884    p_Test(ph, r); n_Test(pGetCoeff(ph), C);
2885    assume(n_GreaterZero(pGetCoeff(ph), C)); // ??
2886/*
2887    if(!n_GreaterZero(pGetCoeff(ph),C))
2888    {
2889      ph = p_Neg(ph,r);
2890      c = n_InpNeg(c, C);
2891    }
2892*/
2893    return;
2894  }
2895#endif
2896
2897
2898
2899
2900  if(1)
2901  {
2902    h = n_Init(1,r->cf);
2903    while (p!=NULL)
2904    {
2905      n_Normalize(pGetCoeff(p),r->cf);
2906      d=n_NormalizeHelper(h,pGetCoeff(p),r->cf);
2907      n_Delete(&h,r->cf);
2908      h=d;
2909      pIter(p);
2910    }
2911    c=h;
2912    /* contains the 1/lcm of all denominators */
2913    if(!n_IsOne(h,r->cf))
2914    {
2915      p = ph;
2916      while (p!=NULL)
2917      {
2918        /* should be:
2919        * number hh;
2920        * nGetDenom(p->coef,&hh);
2921        * nMult(&h,&hh,&d);
2922        * nNormalize(d);
2923        * nDelete(&hh);
2924        * nMult(d,p->coef,&hh);
2925        * nDelete(&d);
2926        * nDelete(&(p->coef));
2927        * p->coef =hh;
2928        */
2929        d=n_Mult(h,pGetCoeff(p),r->cf);
2930        n_Normalize(d,r->cf);
2931        p_SetCoeff(p,d,r);
2932        pIter(p);
2933      }
2934      if (rField_is_Q_a(r))
2935      {
2936        loop
2937        {
2938          h = n_Init(1,r->cf);
2939          p=ph;
2940          while (p!=NULL)
2941          {
2942            d=n_NormalizeHelper(h,pGetCoeff(p),r->cf);
2943            n_Delete(&h,r->cf);
2944            h=d;
2945            pIter(p);
2946          }
2947          /* contains the 1/lcm of all denominators */
2948          if(!n_IsOne(h,r->cf))
2949          {
2950            p = ph;
2951            while (p!=NULL)
2952            {
2953              /* should be:
2954              * number hh;
2955              * nGetDenom(p->coef,&hh);
2956              * nMult(&h,&hh,&d);
2957              * nNormalize(d);
2958              * nDelete(&hh);
2959              * nMult(d,p->coef,&hh);
2960              * nDelete(&d);
2961              * nDelete(&(p->coef));
2962              * p->coef =hh;
2963              */
2964              d=n_Mult(h,pGetCoeff(p),r->cf);
2965              n_Normalize(d,r->cf);
2966              p_SetCoeff(p,d,r);
2967              pIter(p);
2968            }
2969            number t=n_Mult(c,h,r->cf);
2970            n_Delete(&c,r->cf);
2971            c=t;
2972          }
2973          else
2974          {
2975            break;
2976          }
2977          n_Delete(&h,r->cf);
2978        }
2979      }
2980    }
2981  }
2982
2983  if(!n_GreaterZero(pGetCoeff(ph),C))
2984  {
2985    ph = p_Neg(ph,r);
2986    c = n_InpNeg(c, C);
2987  }
2988
2989}
2990
2991  // normalization: for poly over Q: make poly primitive, integral
2992  //                              Qa make poly integral with leading
2993  //                                  coefficient minimal in N
2994  //                            Q(t) make poly primitive, integral
2995
2996void p_ProjectiveUnique(poly ph, const ring r)
2997{
2998  if( ph == NULL )
2999    return;
3000
3001  assume( r != NULL ); assume( r->cf != NULL ); const coeffs C = r->cf;
3002
3003  number h;
3004  poly p;
3005
3006#ifdef HAVE_RINGS
3007  if (rField_is_Ring(r))
3008  {
3009    p_Content(ph,r);
3010    if(!n_GreaterZero(pGetCoeff(ph),C)) ph = p_Neg(ph,r);
3011        assume( n_GreaterZero(pGetCoeff(ph),C) );
3012    return;
3013  }
3014#endif
3015
3016  if (rField_is_Zp(r) && TEST_OPT_INTSTRATEGY)
3017  {
3018    assume( n_GreaterZero(pGetCoeff(ph),C) );
3019    if(!n_GreaterZero(pGetCoeff(ph),C)) ph = p_Neg(ph,r);
3020    return;
3021  }
3022  p = ph;
3023
3024  assume(p != NULL);
3025
3026  if(pNext(p)==NULL) // a monomial
3027  {
3028    p_SetCoeff(p, n_Init(1, C), r);
3029    return;
3030  }
3031
3032  assume(pNext(p)!=NULL);
3033
3034  if(!rField_is_Q(r) && !nCoeff_is_transExt(C))
3035  {
3036    h = p_GetCoeff(p, C);
3037    number hInv = n_Invers(h, C);
3038    pIter(p);
3039    while (p!=NULL)
3040    {
3041      p_SetCoeff(p, n_Mult(p_GetCoeff(p, C), hInv, C), r);
3042      pIter(p);
3043    }
3044    n_Delete(&hInv, C);
3045    p = ph;
3046    p_SetCoeff(p, n_Init(1, C), r);
3047  }
3048
3049  p_Cleardenom(ph, r); //performs also a p_Content
3050 
3051 
3052    /* normalize ph over a transcendental extension s.t.
3053       lead (ph) is > 0 if extRing->cf == Q
3054       or lead (ph) is monic if extRing->cf == Zp*/
3055  if (nCoeff_is_transExt(C))
3056  {
3057    p= ph;
3058    h= p_GetCoeff (p, C);
3059    fraction f = (fraction) h;
3060    number n=p_GetCoeff (NUM (f),C->extRing->cf);
3061    if (rField_is_Q (C->extRing))
3062    {
3063      if (!n_GreaterZero(n,C->extRing->cf))
3064      {
3065        p=p_Neg (p,r);
3066      }
3067    }
3068    else if (rField_is_Zp(C->extRing))
3069    {
3070      if (!n_IsOne (n, C->extRing->cf))
3071      {
3072        n=n_Invers (n,C->extRing->cf);
3073        nMapFunc nMap;
3074        nMap= n_SetMap (C->extRing->cf, C);
3075        number ninv= nMap (n,C->extRing->cf, C);
3076        p=p_Mult_nn (p, ninv, r);
3077        n_Delete (&ninv, C);
3078        n_Delete (&n, C->extRing->cf);
3079      }
3080    }
3081    p= ph;
3082  }
3083
3084  return;
3085}
3086
3087#if 0   /*unused*/
3088number p_GetAllDenom(poly ph, const ring r)
3089{
3090  number d=n_Init(1,r->cf);
3091  poly p = ph;
3092
3093  while (p!=NULL)
3094  {
3095    number h=n_GetDenom(pGetCoeff(p),r->cf);
3096    if (!n_IsOne(h,r->cf))
3097    {
3098      number dd=n_Mult(d,h,r->cf);
3099      n_Delete(&d,r->cf);
3100      d=dd;
3101    }
3102    n_Delete(&h,r->cf);
3103    pIter(p);
3104  }
3105  return d;
3106}
3107#endif
3108
3109int p_Size(poly p, const ring r)
3110{
3111  int count = 0;
3112  while ( p != NULL )
3113  {
3114    count+= n_Size( pGetCoeff( p ), r->cf );
3115    pIter( p );
3116  }
3117  return count;
3118}
3119
3120/*2
3121*make p homogeneous by multiplying the monomials by powers of x_varnum
3122*assume: deg(var(varnum))==1
3123*/
3124poly p_Homogen (poly p, int varnum, const ring r)
3125{
3126  pFDegProc deg;
3127  if (r->pLexOrder && (r->order[0]==ringorder_lp))
3128    deg=p_Totaldegree;
3129  else
3130    deg=r->pFDeg;
3131
3132  poly q=NULL, qn;
3133  int  o,ii;
3134  sBucket_pt bp;
3135
3136  if (p!=NULL)
3137  {
3138    if ((varnum < 1) || (varnum > rVar(r)))
3139    {
3140      return NULL;
3141    }
3142    o=deg(p,r);
3143    q=pNext(p);
3144    while (q != NULL)
3145    {
3146      ii=deg(q,r);
3147      if (ii>o) o=ii;
3148      pIter(q);
3149    }
3150    q = p_Copy(p,r);
3151    bp = sBucketCreate(r);
3152    while (q != NULL)
3153    {
3154      ii = o-deg(q,r);
3155      if (ii!=0)
3156      {
3157        p_AddExp(q,varnum, (long)ii,r);
3158        p_Setm(q,r);
3159      }
3160      qn = pNext(q);
3161      pNext(q) = NULL;
3162      sBucket_Add_p(bp, q, 1);
3163      q = qn;
3164    }
3165    sBucketDestroyAdd(bp, &q, &ii);
3166  }
3167  return q;
3168}
3169
3170/*2
3171*tests if p is homogeneous with respect to the actual weigths
3172*/
3173BOOLEAN p_IsHomogeneous (poly p, const ring r)
3174{
3175  poly qp=p;
3176  int o;
3177
3178  if ((p == NULL) || (pNext(p) == NULL)) return TRUE;
3179  pFDegProc d;
3180  if (r->pLexOrder && (r->order[0]==ringorder_lp))
3181    d=p_Totaldegree;
3182  else
3183    d=r->pFDeg;
3184  o = d(p,r);
3185  do
3186  {
3187    if (d(qp,r) != o) return FALSE;
3188    pIter(qp);
3189  }
3190  while (qp != NULL);
3191  return TRUE;
3192}
3193
3194/*----------utilities for syzygies--------------*/
3195BOOLEAN   p_VectorHasUnitB(poly p, int * k, const ring r)
3196{
3197  poly q=p,qq;
3198  int i;
3199
3200  while (q!=NULL)
3201  {
3202    if (p_LmIsConstantComp(q,r))
3203    {
3204      i = p_GetComp(q,r);
3205      qq = p;
3206      while ((qq != q) && (p_GetComp(qq,r) != i)) pIter(qq);
3207      if (qq == q)
3208      {
3209        *k = i;
3210        return TRUE;
3211      }
3212      else
3213        pIter(q);
3214    }
3215    else pIter(q);
3216  }
3217  return FALSE;
3218}
3219
3220void   p_VectorHasUnit(poly p, int * k, int * len, const ring r)
3221{
3222  poly q=p,qq;
3223  int i,j=0;
3224
3225  *len = 0;
3226  while (q!=NULL)
3227  {
3228    if (p_LmIsConstantComp(q,r))
3229    {
3230      i = p_GetComp(q,r);
3231      qq = p;
3232      while ((qq != q) && (p_GetComp(qq,r) != i)) pIter(qq);
3233      if (qq == q)
3234      {
3235       j = 0;
3236       while (qq!=NULL)
3237       {
3238         if (p_GetComp(qq,r)==i) j++;
3239        pIter(qq);
3240       }
3241       if ((*len == 0) || (j<*len))
3242       {
3243         *len = j;
3244         *k = i;
3245       }
3246      }
3247    }
3248    pIter(q);
3249  }
3250}
3251
3252poly p_TakeOutComp1(poly * p, int k, const ring r)
3253{
3254  poly q = *p;
3255
3256  if (q==NULL) return NULL;
3257
3258  poly qq=NULL,result = NULL;
3259
3260  if (p_GetComp(q,r)==k)
3261  {
3262    result = q; /* *p */
3263    while ((q!=NULL) && (p_GetComp(q,r)==k))
3264    {
3265      p_SetComp(q,0,r);
3266      p_SetmComp(q,r);
3267      qq = q;
3268      pIter(q);
3269    }
3270    *p = q;
3271    pNext(qq) = NULL;
3272  }
3273  if (q==NULL) return result;
3274//  if (pGetComp(q) > k) pGetComp(q)--;
3275  while (pNext(q)!=NULL)
3276  {
3277    if (p_GetComp(pNext(q),r)==k)
3278    {
3279      if (result==NULL)
3280      {
3281        result = pNext(q);
3282        qq = result;
3283      }
3284      else
3285      {
3286        pNext(qq) = pNext(q);
3287        pIter(qq);
3288      }
3289      pNext(q) = pNext(pNext(q));
3290      pNext(qq) =NULL;
3291      p_SetComp(qq,0,r);
3292      p_SetmComp(qq,r);
3293    }
3294    else
3295    {
3296      pIter(q);
3297//      if (pGetComp(q) > k) pGetComp(q)--;
3298    }
3299  }
3300  return result;
3301}
3302
3303poly p_TakeOutComp(poly * p, int k, const ring r)
3304{
3305  poly q = *p,qq=NULL,result = NULL;
3306
3307  if (q==NULL) return NULL;
3308  BOOLEAN use_setmcomp=rOrd_SetCompRequiresSetm(r);
3309  if (p_GetComp(q,r)==k)
3310  {
3311    result = q;
3312    do
3313    {
3314      p_SetComp(q,0,r);
3315      if (use_setmcomp) p_SetmComp(q,r);
3316      qq = q;
3317      pIter(q);
3318    }
3319    while ((q!=NULL) && (p_GetComp(q,r)==k));
3320    *p = q;
3321    pNext(qq) = NULL;
3322  }
3323  if (q==NULL) return result;
3324  if (p_GetComp(q,r) > k)
3325  {
3326    p_SubComp(q,1,r);
3327    if (use_setmcomp) p_SetmComp(q,r);
3328  }
3329  poly pNext_q;
3330  while ((pNext_q=pNext(q))!=NULL)
3331  {
3332    if (p_GetComp(pNext_q,r)==k)
3333    {
3334      if (result==NULL)
3335      {
3336        result = pNext_q;
3337        qq = result;
3338      }
3339      else
3340      {
3341        pNext(qq) = pNext_q;
3342        pIter(qq);
3343      }
3344      pNext(q) = pNext(pNext_q);
3345      pNext(qq) =NULL;
3346      p_SetComp(qq,0,r);
3347      if (use_setmcomp) p_SetmComp(qq,r);
3348    }
3349    else
3350    {
3351      /*pIter(q);*/ q=pNext_q;
3352      if (p_GetComp(q,r) > k)
3353      {
3354        p_SubComp(q,1,r);
3355        if (use_setmcomp) p_SetmComp(q,r);
3356      }
3357    }
3358  }
3359  return result;
3360}
3361
3362// Splits *p into two polys: *q which consists of all monoms with
3363// component == comp and *p of all other monoms *lq == pLength(*q)
3364void p_TakeOutComp(poly *r_p, long comp, poly *r_q, int *lq, const ring r)
3365{
3366  spolyrec pp, qq;
3367  poly p, q, p_prev;
3368  int l = 0;
3369
3370#ifdef HAVE_ASSUME
3371  int lp = pLength(*r_p);
3372#endif
3373
3374  pNext(&pp) = *r_p;
3375  p = *r_p;
3376  p_prev = &pp;
3377  q = &qq;
3378
3379  while(p != NULL)
3380  {
3381    while (p_GetComp(p,r) == comp)
3382    {
3383      pNext(q) = p;
3384      pIter(q);
3385      p_SetComp(p, 0,r);
3386      p_SetmComp(p,r);
3387      pIter(p);
3388      l++;
3389      if (p == NULL)
3390      {
3391        pNext(p_prev) = NULL;
3392        goto Finish;
3393      }
3394    }
3395    pNext(p_prev) = p;
3396    p_prev = p;
3397    pIter(p);
3398  }
3399
3400  Finish:
3401  pNext(q) = NULL;
3402  *r_p = pNext(&pp);
3403  *r_q = pNext(&qq);
3404  *lq = l;
3405#ifdef HAVE_ASSUME
3406  assume(pLength(*r_p) + pLength(*r_q) == lp);
3407#endif
3408  p_Test(*r_p,r);
3409  p_Test(*r_q,r);
3410}
3411
3412void p_DeleteComp(poly * p,int k, const ring r)
3413{
3414  poly q;
3415
3416  while ((*p!=NULL) && (p_GetComp(*p,r)==k)) p_LmDelete(p,r);
3417  if (*p==NULL) return;
3418  q = *p;
3419  if (p_GetComp(q,r)>k)
3420  {
3421    p_SubComp(q,1,r);
3422    p_SetmComp(q,r);
3423  }
3424  while (pNext(q)!=NULL)
3425  {
3426    if (p_GetComp(pNext(q),r)==k)
3427      p_LmDelete(&(pNext(q)),r);
3428    else
3429    {
3430      pIter(q);
3431      if (p_GetComp(q,r)>k)
3432      {
3433        p_SubComp(q,1,r);
3434        p_SetmComp(q,r);
3435      }
3436    }
3437  }
3438}
3439
3440/*2
3441* convert a vector to a set of polys,
3442* allocates the polyset, (entries 0..(*len)-1)
3443* the vector will not be changed
3444*/
3445void  p_Vec2Polys(poly v, poly* *p, int *len, const ring r)
3446{
3447  poly h;
3448  int k;
3449
3450  *len=p_MaxComp(v,r);
3451  if (*len==0) *len=1;
3452  *p=(poly*)omAlloc0((*len)*sizeof(poly));
3453  while (v!=NULL)
3454  {
3455    h=p_Head(v,r);
3456    k=p_GetComp(h,r);
3457    p_SetComp(h,0,r);
3458    (*p)[k-1]=p_Add_q((*p)[k-1],h,r);
3459    pIter(v);
3460  }
3461}
3462
3463//
3464// resets the pFDeg and pLDeg: if pLDeg is not given, it is
3465// set to currRing->pLDegOrig, i.e. to the respective LDegProc which
3466// only uses pFDeg (and not p_Deg, or pTotalDegree, etc)
3467void pSetDegProcs(ring r, pFDegProc new_FDeg, pLDegProc new_lDeg)
3468{
3469  assume(new_FDeg != NULL);
3470  r->pFDeg = new_FDeg;
3471
3472  if (new_lDeg == NULL)
3473    new_lDeg = r->pLDegOrig;
3474
3475  r->pLDeg = new_lDeg;
3476}
3477
3478// restores pFDeg and pLDeg:
3479void pRestoreDegProcs(ring r, pFDegProc old_FDeg, pLDegProc old_lDeg)
3480{
3481  assume(old_FDeg != NULL && old_lDeg != NULL);
3482  r->pFDeg = old_FDeg;
3483  r->pLDeg = old_lDeg;
3484}
3485
3486/*-------- several access procedures to monomials -------------------- */
3487/*
3488* the module weights for std
3489*/
3490static pFDegProc pOldFDeg;
3491static pLDegProc pOldLDeg;
3492static BOOLEAN pOldLexOrder;
3493
3494static long pModDeg(poly p, ring r)
3495{
3496  long d=pOldFDeg(p, r);
3497  int c=p_GetComp(p, r);
3498  if ((c>0) && ((r->pModW)->range(c-1))) d+= (*(r->pModW))[c-1];
3499  return d;
3500  //return pOldFDeg(p, r)+(*pModW)[p_GetComp(p, r)-1];
3501}
3502
3503void p_SetModDeg(intvec *w, ring r)
3504{
3505  if (w!=NULL)
3506  {
3507    r->pModW = w;
3508    pOldFDeg = r->pFDeg;
3509    pOldLDeg = r->pLDeg;
3510    pOldLexOrder = r->pLexOrder;
3511    pSetDegProcs(r,pModDeg);
3512    r->pLexOrder = TRUE;
3513  }
3514  else
3515  {
3516    r->pModW = NULL;
3517    pRestoreDegProcs(r,pOldFDeg, pOldLDeg);
3518    r->pLexOrder = pOldLexOrder;
3519  }
3520}
3521
3522/*2
3523* handle memory request for sets of polynomials (ideals)
3524* l is the length of *p, increment is the difference (may be negative)
3525*/
3526void pEnlargeSet(poly* *p, int l, int increment)
3527{
3528  poly* h;
3529
3530  h=(poly*)omReallocSize((poly*)*p,l*sizeof(poly),(l+increment)*sizeof(poly));
3531  if (increment>0)
3532  {
3533    //for (i=l; i<l+increment; i++)
3534    //  h[i]=NULL;
3535    memset(&(h[l]),0,increment*sizeof(poly));
3536  }
3537  *p=h;
3538}
3539
3540/*2
3541*divides p1 by its leading coefficient
3542*/
3543void p_Norm(poly p1, const ring r)
3544{
3545#ifdef HAVE_RINGS
3546  if (rField_is_Ring(r))
3547  {
3548    if (!n_IsUnit(pGetCoeff(p1), r->cf)) return;
3549    // Werror("p_Norm not possible in the case of coefficient rings.");
3550  }
3551  else
3552#endif
3553  if (p1!=NULL)
3554  {
3555    if (pNext(p1)==NULL)
3556    {
3557      p_SetCoeff(p1,n_Init(1,r->cf),r);
3558      return;
3559    }
3560    poly h;
3561    if (!n_IsOne(pGetCoeff(p1),r->cf))
3562    {
3563      number k, c;
3564      n_Normalize(pGetCoeff(p1),r->cf);
3565      k = pGetCoeff(p1);
3566      c = n_Init(1,r->cf);
3567      pSetCoeff0(p1,c);
3568      h = pNext(p1);
3569      while (h!=NULL)
3570      {
3571        c=n_Div(pGetCoeff(h),k,r->cf);
3572        // no need to normalize: Z/p, R
3573        // normalize already in nDiv: Q_a, Z/p_a
3574        // remains: Q
3575        if (rField_is_Q(r) && (!n_IsOne(c,r->cf))) n_Normalize(c,r->cf);
3576        p_SetCoeff(h,c,r);
3577        pIter(h);
3578      }
3579      n_Delete(&k,r->cf);
3580    }
3581    else
3582    {
3583      //if (r->cf->cfNormalize != nDummy2) //TODO: OPTIMIZE
3584      {
3585        h = pNext(p1);
3586        while (h!=NULL)
3587        {
3588          n_Normalize(pGetCoeff(h),r->cf);
3589          pIter(h);
3590        }
3591      }
3592    }
3593  }
3594}
3595
3596/*2
3597*normalize all coefficients
3598*/
3599void p_Normalize(poly p,const ring r)
3600{
3601  if (rField_has_simple_inverse(r)) return; /* Z/p, GF(p,n), R, long R/C */
3602  while (p!=NULL)
3603  {
3604#ifdef LDEBUG
3605    n_Test(pGetCoeff(p), r->cf);
3606#endif
3607    n_Normalize(pGetCoeff(p),r->cf);
3608    pIter(p);
3609  }
3610}
3611
3612// splits p into polys with Exp(n) == 0 and Exp(n) != 0
3613// Poly with Exp(n) != 0 is reversed
3614static void p_SplitAndReversePoly(poly p, int n, poly *non_zero, poly *zero, const ring r)
3615{
3616  if (p == NULL)
3617  {
3618    *non_zero = NULL;
3619    *zero = NULL;
3620    return;
3621  }
3622  spolyrec sz;
3623  poly z, n_z, next;
3624  z = &sz;
3625  n_z = NULL;
3626
3627  while(p != NULL)
3628  {
3629    next = pNext(p);
3630    if (p_GetExp(p, n,r) == 0)
3631    {
3632      pNext(z) = p;
3633      pIter(z);
3634    }
3635    else
3636    {
3637      pNext(p) = n_z;
3638      n_z = p;
3639    }
3640    p = next;
3641  }
3642  pNext(z) = NULL;
3643  *zero = pNext(&sz);
3644  *non_zero = n_z;
3645}
3646/*3
3647* substitute the n-th variable by 1 in p
3648* destroy p
3649*/
3650static poly p_Subst1 (poly p,int n, const ring r)
3651{
3652  poly qq=NULL, result = NULL;
3653  poly zero=NULL, non_zero=NULL;
3654
3655  // reverse, so that add is likely to be linear
3656  p_SplitAndReversePoly(p, n, &non_zero, &zero,r);
3657
3658  while (non_zero != NULL)
3659  {
3660    assume(p_GetExp(non_zero, n,r) != 0);
3661    qq = non_zero;
3662    pIter(non_zero);
3663    qq->next = NULL;
3664    p_SetExp(qq,n,0,r);
3665    p_Setm(qq,r);
3666    result = p_Add_q(result,qq,r);
3667  }
3668  p = p_Add_q(result, zero,r);
3669  p_Test(p,r);
3670  return p;
3671}
3672
3673/*3
3674* substitute the n-th variable by number e in p
3675* destroy p
3676*/
3677static poly p_Subst2 (poly p,int n, number e, const ring r)
3678{
3679  assume( ! n_IsZero(e,r->cf) );
3680  poly qq,result = NULL;
3681  number nn, nm;
3682  poly zero, non_zero;
3683
3684  // reverse, so that add is likely to be linear
3685  p_SplitAndReversePoly(p, n, &non_zero, &zero,r);
3686
3687  while (non_zero != NULL)
3688  {
3689    assume(p_GetExp(non_zero, n, r) != 0);
3690    qq = non_zero;
3691    pIter(non_zero);
3692    qq->next = NULL;
3693    n_Power(e, p_GetExp(qq, n, r), &nn,r->cf);
3694    nm = n_Mult(nn, pGetCoeff(qq),r->cf);
3695#ifdef HAVE_RINGS
3696    if (n_IsZero(nm,r->cf))
3697    {
3698      p_LmFree(&qq,r);
3699      n_Delete(&nm,r->cf);
3700    }
3701    else
3702#endif
3703    {
3704      p_SetCoeff(qq, nm,r);
3705      p_SetExp(qq, n, 0,r);
3706      p_Setm(qq,r);
3707      result = p_Add_q(result,qq,r);
3708    }
3709    n_Delete(&nn,r->cf);
3710  }
3711  p = p_Add_q(result, zero,r);
3712  p_Test(p,r);
3713  return p;
3714}
3715
3716
3717/* delete monoms whose n-th exponent is different from zero */
3718static poly p_Subst0(poly p, int n, const ring r)
3719{
3720  spolyrec res;
3721  poly h = &res;
3722  pNext(h) = p;
3723
3724  while (pNext(h)!=NULL)
3725  {
3726    if (p_GetExp(pNext(h),n,r)!=0)
3727    {
3728      p_LmDelete(&pNext(h),r);
3729    }
3730    else
3731    {
3732      pIter(h);
3733    }
3734  }
3735  p_Test(pNext(&res),r);
3736  return pNext(&res);
3737}
3738
3739/*2
3740* substitute the n-th variable by e in p
3741* destroy p
3742*/
3743poly p_Subst(poly p, int n, poly e, const ring r)
3744{
3745  if (e == NULL) return p_Subst0(p, n,r);
3746
3747  if (p_IsConstant(e,r))
3748  {
3749    if (n_IsOne(pGetCoeff(e),r->cf)) return p_Subst1(p,n,r);
3750    else return p_Subst2(p, n, pGetCoeff(e),r);
3751  }
3752
3753#ifdef HAVE_PLURAL
3754  if (rIsPluralRing(r))
3755  {
3756    return nc_pSubst(p,n,e,r);
3757  }
3758#endif
3759
3760  int exponent,i;
3761  poly h, res, m;
3762  int *me,*ee;
3763  number nu,nu1;
3764
3765  me=(int *)omAlloc((rVar(r)+1)*sizeof(int));
3766  ee=(int *)omAlloc((rVar(r)+1)*sizeof(int));
3767  if (e!=NULL) p_GetExpV(e,ee,r);
3768  res=NULL;
3769  h=p;
3770  while (h!=NULL)
3771  {
3772    if ((e!=NULL) || (p_GetExp(h,n,r)==0))
3773    {
3774      m=p_Head(h,r);
3775      p_GetExpV(m,me,r);
3776      exponent=me[n];
3777      me[n]=0;
3778      for(i=rVar(r);i>0;i--)
3779        me[i]+=exponent*ee[i];
3780      p_SetExpV(m,me,r);
3781      if (e!=NULL)
3782      {
3783        n_Power(pGetCoeff(e),exponent,&nu,r->cf);
3784        nu1=n_Mult(pGetCoeff(m),nu,r->cf);
3785        n_Delete(&nu,r->cf);
3786        p_SetCoeff(m,nu1,r);
3787      }
3788      res=p_Add_q(res,m,r);
3789    }
3790    p_LmDelete(&h,r);
3791  }
3792  omFreeSize((ADDRESS)me,(rVar(r)+1)*sizeof(int));
3793  omFreeSize((ADDRESS)ee,(rVar(r)+1)*sizeof(int));
3794  return res;
3795}
3796
3797/*2
3798 * returns a re-ordered convertion of a number as a polynomial,
3799 * with permutation of parameters
3800 * NOTE: this only works for Frank's alg. & trans. fields
3801 */
3802poly n_PermNumber(const number z, const int *par_perm, const int , const ring src, const ring dst)
3803{
3804#if 0
3805  PrintS("\nSource Ring: \n");
3806  rWrite(src);
3807
3808  if(0)
3809  {
3810    number zz = n_Copy(z, src->cf);
3811    PrintS("z: "); n_Write(zz, src);
3812    n_Delete(&zz, src->cf);
3813  }
3814
3815  PrintS("\nDestination Ring: \n");
3816  rWrite(dst);
3817
3818  /*Print("\nOldPar: %d\n", OldPar);
3819  for( int i = 1; i <= OldPar; i++ )
3820  {
3821    Print("par(%d) -> par/var (%d)\n", i, par_perm[i-1]);
3822  }*/
3823#endif
3824  if( z == NULL )
3825     return NULL;
3826
3827  const coeffs srcCf = src->cf;
3828  assume( srcCf != NULL );
3829
3830  assume( !nCoeff_is_GF(srcCf) );
3831  assume( src->cf->extRing!=NULL );
3832
3833  poly zz = NULL;
3834
3835  const ring srcExtRing = srcCf->extRing;
3836  assume( srcExtRing != NULL );
3837
3838  const coeffs dstCf = dst->cf;
3839  assume( dstCf != NULL );
3840
3841  if( nCoeff_is_algExt(srcCf) ) // nCoeff_is_GF(srcCf)?
3842  {
3843    zz = (poly) z;
3844    if( zz == NULL ) return NULL;
3845  }
3846  else if (nCoeff_is_transExt(srcCf))
3847  {
3848    assume( !IS0(z) );
3849
3850    zz = NUM(z);
3851    p_Test (zz, srcExtRing);
3852
3853    if( zz == NULL ) return NULL;
3854    if( !DENIS1(z) )
3855    {
3856      if (p_IsConstant(DEN(z),srcExtRing))
3857      {
3858        number n=pGetCoeff(DEN(z));
3859        zz=p_Div_nn(zz,n,srcExtRing);
3860        p_Normalize(zz,srcExtRing);
3861      }
3862      else
3863        WarnS("Not defined: Cannot map a rational fraction and make a polynomial out of it! Ignoring the denumerator.");
3864    }
3865  }
3866  else
3867  {
3868    assume (FALSE);
3869    Werror("Number permutation is not implemented for this data yet!");
3870    return NULL;
3871  }
3872
3873  assume( zz != NULL );
3874  p_Test (zz, srcExtRing);
3875
3876  nMapFunc nMap = n_SetMap(srcExtRing->cf, dstCf);
3877
3878  assume( nMap != NULL );
3879
3880  poly qq;
3881  if ((par_perm == NULL) && (rPar(dst) != 0 && rVar (srcExtRing) > 0))
3882  {
3883    int* perm;
3884    perm=(int *)omAlloc0((rVar(srcExtRing)+1)*sizeof(int));
3885    perm[0]= 0;
3886    for(int i=si_min(rVar(srcExtRing),rPar(dst));i>0;i--)
3887      perm[i]=-i;
3888    qq = p_PermPoly(zz, perm, srcExtRing, dst, nMap, NULL, rVar(srcExtRing)-1);
3889    omFreeSize ((ADDRESS)perm, (rVar(srcExtRing)+1)*sizeof(int));
3890  }
3891  else
3892    qq = p_PermPoly(zz, par_perm-1, srcExtRing, dst, nMap, NULL, rVar (srcExtRing)-1);
3893
3894  assume (p_Test (qq, dst));
3895
3896//       poly p_PermPoly (poly p, int * perm, const ring oldRing, const ring dst, nMapFunc nMap, int *par_perm, int OldPar)
3897
3898//  assume( FALSE );  WarnS("longalg missing 2");
3899
3900  return qq;
3901}
3902
3903
3904/*2
3905*returns a re-ordered copy of a polynomial, with permutation of the variables
3906*/
3907poly p_PermPoly (poly p, const int * perm, const ring oldRing, const ring dst,
3908       nMapFunc nMap, const int *par_perm, int OldPar)
3909{
3910#if 0
3911    p_Test(p, oldRing);
3912    PrintS("\np_PermPoly::p: "); p_Write(p, oldRing, oldRing); PrintLn();
3913#endif
3914
3915  const int OldpVariables = rVar(oldRing);
3916  poly result = NULL;
3917  poly result_last = NULL;
3918  poly aq = NULL; /* the map coefficient */
3919  poly qq; /* the mapped monomial */
3920
3921  assume(dst != NULL);
3922  assume(dst->cf != NULL);
3923
3924  while (p != NULL)
3925  {
3926    // map the coefficient
3927    if ( ((OldPar == 0) || (par_perm == NULL) || rField_is_GF(oldRing)) && (nMap != NULL) )
3928    {
3929      qq = p_Init(dst);
3930      assume( nMap != NULL );
3931
3932      number n = nMap(p_GetCoeff(p, oldRing), oldRing->cf, dst->cf);
3933
3934      assume (n_Test (n,dst->cf));
3935
3936      if ( nCoeff_is_algExt(dst->cf) )
3937        n_Normalize(n, dst->cf);
3938
3939      p_GetCoeff(qq, dst) = n;// Note: n can be a ZERO!!!
3940      // coef may be zero:
3941//      p_Test(qq, dst);
3942    }
3943    else
3944    {
3945      qq = p_One(dst);
3946
3947//      aq = naPermNumber(p_GetCoeff(p, oldRing), par_perm, OldPar, oldRing); // no dst???
3948//      poly    n_PermNumber(const number z, const int *par_perm, const int P, const ring src, const ring dst)
3949      aq = n_PermNumber(p_GetCoeff(p, oldRing), par_perm, OldPar, oldRing, dst);
3950
3951      p_Test(aq, dst);
3952
3953      if ( nCoeff_is_algExt(dst->cf) )
3954        p_Normalize(aq,dst);
3955
3956      if (aq == NULL)
3957        p_SetCoeff(qq, n_Init(0, dst->cf),dst); // Very dirty trick!!!
3958
3959      p_Test(aq, dst);
3960    }
3961
3962    if (rRing_has_Comp(dst))
3963       p_SetComp(qq, p_GetComp(p, oldRing), dst);
3964
3965    if ( n_IsZero(pGetCoeff(qq), dst->cf) )
3966    {
3967      p_LmDelete(&qq,dst);
3968      qq = NULL;
3969    }
3970    else
3971    {
3972      // map pars:
3973      int mapped_to_par = 0;
3974      for(int i = 1; i <= OldpVariables; i++)
3975      {
3976        int e = p_GetExp(p, i, oldRing);
3977        if (e != 0)
3978        {
3979          if (perm==NULL)
3980            p_SetExp(qq, i, e, dst);
3981          else if (perm[i]>0)
3982            p_AddExp(qq,perm[i], e/*p_GetExp( p,i,oldRing)*/, dst);
3983          else if (perm[i]<0)
3984          {
3985            number c = p_GetCoeff(qq, dst);
3986            if (rField_is_GF(dst))
3987            {
3988              assume( dst->cf->extRing == NULL );
3989              number ee = n_Param(1, dst);
3990
3991              number eee;
3992              n_Power(ee, e, &eee, dst->cf); //nfDelete(ee,dst);
3993
3994              ee = n_Mult(c, eee, dst->cf);
3995              //nfDelete(c,dst);nfDelete(eee,dst);
3996              pSetCoeff0(qq,ee);
3997            }
3998            else if (nCoeff_is_Extension(dst->cf))
3999            {
4000              const int par = -perm[i];
4001              assume( par > 0 );
4002
4003//              WarnS("longalg missing 3");
4004#if 1
4005              const coeffs C = dst->cf;
4006              assume( C != NULL );
4007
4008              const ring R = C->extRing;
4009              assume( R != NULL );
4010
4011              assume( par <= rVar(R) );
4012
4013              poly pcn; // = (number)c
4014
4015              assume( !n_IsZero(c, C) );
4016
4017              if( nCoeff_is_algExt(C) )
4018                 pcn = (poly) c;
4019               else //            nCoeff_is_transExt(C)
4020                 pcn = NUM(c);
4021
4022              if (pNext(pcn) == NULL) // c->z
4023                p_AddExp(pcn, -perm[i], e, R);
4024              else /* more difficult: we have really to multiply: */
4025              {
4026                poly mmc = p_ISet(1, R);
4027                p_SetExp(mmc, -perm[i], e, R);
4028                p_Setm(mmc, R);
4029
4030                number nnc;
4031                // convert back to a number: number nnc = mmc;
4032                if( nCoeff_is_algExt(C) )
4033                   nnc = (number) mmc;
4034                else //            nCoeff_is_transExt(C)
4035                  nnc = ntInit(mmc, C);
4036
4037                p_GetCoeff(qq, dst) = n_Mult((number)c, nnc, C);
4038                n_Delete((number *)&c, C);
4039                n_Delete((number *)&nnc, C);
4040              }
4041
4042              mapped_to_par=1;
4043#endif
4044            }
4045          }
4046          else
4047          {
4048            /* this variable maps to 0 !*/
4049            p_LmDelete(&qq, dst);
4050            break;
4051          }
4052        }
4053      }
4054      if ( mapped_to_par && qq!= NULL && nCoeff_is_algExt(dst->cf) )
4055      {
4056        number n = p_GetCoeff(qq, dst);
4057        n_Normalize(n, dst->cf);
4058        p_GetCoeff(qq, dst) = n;
4059      }
4060    }
4061    pIter(p);
4062
4063#if 0
4064    p_Test(aq,dst);
4065    PrintS("\naq: "); p_Write(aq, dst, dst); PrintLn();
4066#endif
4067
4068
4069#if 1
4070    if (qq!=NULL)
4071    {
4072      p_Setm(qq,dst);
4073
4074      p_Test(aq,dst);
4075      p_Test(qq,dst);
4076
4077#if 0
4078    p_Test(qq,dst);
4079    PrintS("\nqq: "); p_Write(qq, dst, dst); PrintLn();
4080#endif
4081
4082      if (aq!=NULL)
4083         qq=p_Mult_q(aq,qq,dst);
4084
4085      aq = qq;
4086
4087      while (pNext(aq) != NULL) pIter(aq);
4088
4089      if (result_last==NULL)
4090      {
4091        result=qq;
4092      }
4093      else
4094      {
4095        pNext(result_last)=qq;
4096      }
4097      result_last=aq;
4098      aq = NULL;
4099    }
4100    else if (aq!=NULL)
4101    {
4102      p_Delete(&aq,dst);
4103    }
4104  }
4105
4106  result=p_SortAdd(result,dst);
4107#else
4108  //  if (qq!=NULL)
4109  //  {
4110  //    pSetm(qq);
4111  //    pTest(qq);
4112  //    pTest(aq);
4113  //    if (aq!=NULL) qq=pMult(aq,qq);
4114  //    aq = qq;
4115  //    while (pNext(aq) != NULL) pIter(aq);
4116  //    pNext(aq) = result;
4117  //    aq = NULL;
4118  //    result = qq;
4119  //  }
4120  //  else if (aq!=NULL)
4121  //  {
4122  //    pDelete(&aq);
4123  //  }
4124  //}
4125  //p = result;
4126  //result = NULL;
4127  //while (p != NULL)
4128  //{
4129  //  qq = p;
4130  //  pIter(p);
4131  //  qq->next = NULL;
4132  //  result = pAdd(result, qq);
4133  //}
4134#endif
4135  p_Test(result,dst);
4136
4137#if 0
4138  p_Test(result,dst);
4139  PrintS("\nresult: "); p_Write(result,dst,dst); PrintLn();
4140#endif
4141  return result;
4142}
4143/**************************************************************
4144 *
4145 * Jet
4146 *
4147 **************************************************************/
4148
4149poly pp_Jet(poly p, int m, const ring R)
4150{
4151  poly r=NULL;
4152  poly t=NULL;
4153
4154  while (p!=NULL)
4155  {
4156    if (p_Totaldegree(p,R)<=m)
4157    {
4158      if (r==NULL)
4159        r=p_Head(p,R);
4160      else
4161      if (t==NULL)
4162      {
4163        pNext(r)=p_Head(p,R);
4164        t=pNext(r);
4165      }
4166      else
4167      {
4168        pNext(t)=p_Head(p,R);
4169        pIter(t);
4170      }
4171    }
4172    pIter(p);
4173  }
4174  return r;
4175}
4176
4177poly p_Jet(poly p, int m,const ring R)
4178{
4179  while((p!=NULL) && (p_Totaldegree(p,R)>m)) p_LmDelete(&p,R);
4180  if (p==NULL) return NULL;
4181  poly r=p;
4182  while (pNext(p)!=NULL)
4183  {
4184    if (p_Totaldegree(pNext(p),R)>m)
4185    {
4186      p_LmDelete(&pNext(p),R);
4187    }
4188    else
4189      pIter(p);
4190  }
4191  return r;
4192}
4193
4194poly pp_JetW(poly p, int m, short *w, const ring R)
4195{
4196  poly r=NULL;
4197  poly t=NULL;
4198  while (p!=NULL)
4199  {
4200    if (totaldegreeWecart_IV(p,R,w)<=m)
4201    {
4202      if (r==NULL)
4203        r=p_Head(p,R);
4204      else
4205      if (t==NULL)
4206      {
4207        pNext(r)=p_Head(p,R);
4208        t=pNext(r);
4209      }
4210      else
4211      {
4212        pNext(t)=p_Head(p,R);
4213        pIter(t);
4214      }
4215    }
4216    pIter(p);
4217  }
4218  return r;
4219}
4220
4221poly p_JetW(poly p, int m, short *w, const ring R)
4222{
4223  while((p!=NULL) && (totaldegreeWecart_IV(p,R,w)>m)) p_LmDelete(&p,R);
4224  if (p==NULL) return NULL;
4225  poly r=p;
4226  while (pNext(p)!=NULL)
4227  {
4228    if (totaldegreeWecart_IV(pNext(p),R,w)>m)
4229    {
4230      p_LmDelete(&pNext(p),R);
4231    }
4232    else
4233      pIter(p);
4234  }
4235  return r;
4236}
4237
4238/*************************************************************/
4239int p_MinDeg(poly p,intvec *w, const ring R)
4240{
4241  if(p==NULL)
4242    return -1;
4243  int d=-1;
4244  while(p!=NULL)
4245  {
4246    int d0=0;
4247    for(int j=0;j<rVar(R);j++)
4248      if(w==NULL||j>=w->length())
4249        d0+=p_GetExp(p,j+1,R);
4250      else
4251        d0+=(*w)[j]*p_GetExp(p,j+1,R);
4252    if(d0<d||d==-1)
4253      d=d0;
4254    pIter(p);
4255  }
4256  return d;
4257}
4258
4259/***************************************************************/
4260
4261poly p_Series(int n,poly p,poly u, intvec *w, const ring R)
4262{
4263  short *ww=iv2array(w,R);
4264  if(p!=NULL)
4265  {
4266    if(u==NULL)
4267      p=p_JetW(p,n,ww,R);
4268    else
4269      p=p_JetW(p_Mult_q(p,p_Invers(n-p_MinDeg(p,w,R),u,w,R),R),n,ww,R);
4270  }
4271  omFreeSize((ADDRESS)ww,(rVar(R)+1)*sizeof(short));
4272  return p;
4273}
4274
4275poly p_Invers(int n,poly u,intvec *w, const ring R)
4276{
4277  if(n<0)
4278    return NULL;
4279  number u0=n_Invers(pGetCoeff(u),R->cf);
4280  poly v=p_NSet(u0,R);
4281  if(n==0)
4282    return v;
4283  short *ww=iv2array(w,R);
4284  poly u1=p_JetW(p_Sub(p_One(R),p_Mult_nn(u,u0,R),R),n,ww,R);
4285  if(u1==NULL)
4286  {
4287    omFreeSize((ADDRESS)ww,(rVar(R)+1)*sizeof(short));
4288    return v;
4289  }
4290  poly v1=p_Mult_nn(p_Copy(u1,R),u0,R);
4291  v=p_Add_q(v,p_Copy(v1,R),R);
4292  for(int i=n/p_MinDeg(u1,w,R);i>1;i--)
4293  {
4294    v1=p_JetW(p_Mult_q(v1,p_Copy(u1,R),R),n,ww,R);
4295    v=p_Add_q(v,p_Copy(v1,R),R);
4296  }
4297  p_Delete(&u1,R);
4298  p_Delete(&v1,R);
4299  omFreeSize((ADDRESS)ww,(rVar(R)+1)*sizeof(short));
4300  return v;
4301}
4302
4303BOOLEAN p_EqualPolys(poly p1,poly p2, const ring r)
4304{
4305  while ((p1 != NULL) && (p2 != NULL))
4306  {
4307    if (! p_LmEqual(p1, p2,r))
4308      return FALSE;
4309    if (! n_Equal(p_GetCoeff(p1,r), p_GetCoeff(p2,r),r->cf ))
4310      return FALSE;
4311    pIter(p1);
4312    pIter(p2);
4313  }
4314  return (p1==p2);
4315}
4316
4317static inline BOOLEAN p_ExpVectorEqual(poly p1, poly p2, const ring r1, const ring r2)
4318{
4319  assume( r1 == r2 || rSamePolyRep(r1, r2) );
4320
4321  p_LmCheckPolyRing1(p1, r1);
4322  p_LmCheckPolyRing1(p2, r2);
4323
4324  int i = r1->ExpL_Size;
4325
4326  assume( r1->ExpL_Size == r2->ExpL_Size );
4327
4328  unsigned long *ep = p1->exp;
4329  unsigned long *eq = p2->exp;
4330
4331  do
4332  {
4333    i--;
4334    if (ep[i] != eq[i]) return FALSE;
4335  }
4336  while (i);
4337
4338  return TRUE;
4339}
4340
4341BOOLEAN p_EqualPolys(poly p1,poly p2, const ring r1, const ring r2)
4342{
4343  assume( r1 == r2 || rSamePolyRep(r1, r2) ); // will be used in rEqual!
4344  assume( r1->cf == r2->cf );
4345
4346  while ((p1 != NULL) && (p2 != NULL))
4347  {
4348    // returns 1 if ExpVector(p)==ExpVector(q): does not compare numbers !!
4349    // #define p_LmEqual(p1, p2, r) p_ExpVectorEqual(p1, p2, r)
4350
4351    if (! p_ExpVectorEqual(p1, p2, r1, r2))
4352      return FALSE;
4353
4354    if (! n_Equal(p_GetCoeff(p1,r1), p_GetCoeff(p2,r2), r1->cf ))
4355      return FALSE;
4356
4357    pIter(p1);
4358    pIter(p2);
4359  }
4360  return (p1==p2);
4361}
4362
4363/*2
4364*returns TRUE if p1 is a skalar multiple of p2
4365*assume p1 != NULL and p2 != NULL
4366*/
4367BOOLEAN p_ComparePolys(poly p1,poly p2, const ring r)
4368{
4369  number n,nn;
4370  pAssume(p1 != NULL && p2 != NULL);
4371
4372  if (!p_LmEqual(p1,p2,r)) //compare leading mons
4373      return FALSE;
4374  if ((pNext(p1)==NULL) && (pNext(p2)!=NULL))
4375     return FALSE;
4376  if ((pNext(p2)==NULL) && (pNext(p1)!=NULL))
4377     return FALSE;
4378  if (pLength(p1) != pLength(p2))
4379    return FALSE;
4380#ifdef HAVE_RINGS
4381  if (rField_is_Ring(r))
4382  {
4383    if (!n_DivBy(p_GetCoeff(p1, r), p_GetCoeff(p2, r), r)) return FALSE;
4384  }
4385#endif
4386  n=n_Div(p_GetCoeff(p1,r),p_GetCoeff(p2,r),r);
4387  while ((p1 != NULL) /*&& (p2 != NULL)*/)
4388  {
4389    if ( ! p_LmEqual(p1, p2,r))
4390    {
4391        n_Delete(&n, r);
4392        return FALSE;
4393    }
4394    if (!n_Equal(p_GetCoeff(p1, r), nn = n_Mult(p_GetCoeff(p2, r),n, r->cf), r->cf))
4395    {
4396      n_Delete(&n, r);
4397      n_Delete(&nn, r);
4398      return FALSE;
4399    }
4400    n_Delete(&nn, r);
4401    pIter(p1);
4402    pIter(p2);
4403  }
4404  n_Delete(&n, r);
4405  return TRUE;
4406}
4407
4408/*2
4409* returns the length of a (numbers of monomials)
4410* respect syzComp
4411*/
4412poly p_Last(const poly p, int &l, const ring r)
4413{
4414  if (p == NULL)
4415  {
4416    l = 0;
4417    return NULL;
4418  }
4419  l = 1;
4420  poly a = p;
4421  if (! rIsSyzIndexRing(r))
4422  {
4423    poly next = pNext(a);
4424    while (next!=NULL)
4425    {
4426      a = next;
4427      next = pNext(a);
4428      l++;
4429    }
4430  }
4431  else
4432  {
4433    int curr_limit = rGetCurrSyzLimit(r);
4434    poly pp = a;
4435    while ((a=pNext(a))!=NULL)
4436    {
4437      if (p_GetComp(a,r)<=curr_limit/*syzComp*/)
4438        l++;
4439      else break;
4440      pp = a;
4441    }
4442    a=pp;
4443  }
4444  return a;
4445}
4446
4447int p_Var(poly m,const ring r)
4448{
4449  if (m==NULL) return 0;
4450  if (pNext(m)!=NULL) return 0;
4451  int i,e=0;
4452  for (i=rVar(r); i>0; i--)
4453  {
4454    int exp=p_GetExp(m,i,r);
4455    if (exp==1)
4456    {
4457      if (e==0) e=i;
4458      else return 0;
4459    }
4460    else if (exp!=0)
4461    {
4462      return 0;
4463    }
4464  }
4465  return e;
4466}
4467
4468/*2
4469*the minimal index of used variables - 1
4470*/
4471int p_LowVar (poly p, const ring r)
4472{
4473  int k,l,lex;
4474
4475  if (p == NULL) return -1;
4476
4477  k = 32000;/*a very large dummy value*/
4478  while (p != NULL)
4479  {
4480    l = 1;
4481    lex = p_GetExp(p,l,r);
4482    while ((l < (rVar(r))) && (lex == 0))
4483    {
4484      l++;
4485      lex = p_GetExp(p,l,r);
4486    }
4487    l--;
4488    if (l < k) k = l;
4489    pIter(p);
4490  }
4491  return k;
4492}
4493
4494/*2
4495* verschiebt die Indizees der Modulerzeugenden um i
4496*/
4497void p_Shift (poly * p,int i, const ring r)
4498{
4499  poly qp1 = *p,qp2 = *p;/*working pointers*/
4500  int     j = p_MaxComp(*p,r),k = p_MinComp(*p,r);
4501
4502  if (j+i < 0) return ;
4503  while (qp1 != NULL)
4504  {
4505    if ((p_GetComp(qp1,r)+i > 0) || ((j == -i) && (j == k)))
4506    {
4507      p_AddComp(qp1,i,r);
4508      p_SetmComp(qp1,r);
4509      qp2 = qp1;
4510      pIter(qp1);
4511    }
4512    else
4513    {
4514      if (qp2 == *p)
4515      {
4516        pIter(*p);
4517        p_LmDelete(&qp2,r);
4518        qp2 = *p;
4519        qp1 = *p;
4520      }
4521      else
4522      {
4523        qp2->next = qp1->next;
4524        if (qp1!=NULL) p_LmDelete(&qp1,r);
4525        qp1 = qp2->next;
4526      }
4527    }
4528  }
4529}
4530
4531/***************************************************************
4532 *
4533 * Storage Managament Routines
4534 *
4535 ***************************************************************/
4536
4537
4538static inline unsigned long GetBitFields(long e,
4539                                         unsigned int s, unsigned int n)
4540{
4541#define Sy_bit_L(x)     (((unsigned long)1L)<<(x))
4542  unsigned int i = 0;
4543  unsigned long  ev = 0L;
4544  assume(n > 0 && s < BIT_SIZEOF_LONG);
4545  do
4546  {
4547    assume(s+i < BIT_SIZEOF_LONG);
4548    if (e > (long) i) ev |= Sy_bit_L(s+i);
4549    else break;
4550    i++;
4551  }
4552  while (i < n);
4553  return ev;
4554}
4555
4556// Short Exponent Vectors are used for fast divisibility tests
4557// ShortExpVectors "squeeze" an exponent vector into one word as follows:
4558// Let n = BIT_SIZEOF_LONG / pVariables.
4559// If n == 0 (i.e. pVariables > BIT_SIZE_OF_LONG), let m == the number
4560// of non-zero exponents. If (m>BIT_SIZEOF_LONG), then sev = ~0, else
4561// first m bits of sev are set to 1.
4562// Otherwise (i.e. pVariables <= BIT_SIZE_OF_LONG)
4563// represented by a bit-field of length n (resp. n+1 for some
4564// exponents). If the value of an exponent is greater or equal to n, then
4565// all of its respective n bits are set to 1. If the value of an exponent
4566// is smaller than n, say m, then only the first m bits of the respective
4567// n bits are set to 1, the others are set to 0.
4568// This way, we have:
4569// exp1 / exp2 ==> (ev1 & ~ev2) == 0, i.e.,
4570// if (ev1 & ~ev2) then exp1 does not divide exp2
4571unsigned long p_GetShortExpVector(poly p, const ring r)
4572{
4573  assume(p != NULL);
4574  if (p == NULL) return 0;
4575  unsigned long ev = 0; // short exponent vector
4576  unsigned int n = BIT_SIZEOF_LONG / r->N; // number of bits per exp
4577  unsigned int m1; // highest bit which is filled with (n+1)
4578  unsigned int i = 0, j=1;
4579
4580  if (n == 0)
4581  {
4582    if (r->N <2*BIT_SIZEOF_LONG)
4583    {
4584      n=1;
4585      m1=0;
4586    }
4587    else
4588    {
4589      for (; j<=(unsigned long) r->N; j++)
4590      {
4591        if (p_GetExp(p,j,r) > 0) i++;
4592        if (i == BIT_SIZEOF_LONG) break;
4593      }
4594      if (i>0)
4595        ev = ~((unsigned long)0) >> ((unsigned long) (BIT_SIZEOF_LONG - i));
4596      return ev;
4597    }
4598  }
4599  else
4600  {
4601    m1 = (n+1)*(BIT_SIZEOF_LONG - n*r->N);
4602  }
4603
4604  n++;
4605  while (i<m1)
4606  {
4607    ev |= GetBitFields(p_GetExp(p, j,r), i, n);
4608    i += n;
4609    j++;
4610  }
4611
4612  n--;
4613  while (i<BIT_SIZEOF_LONG)
4614  {
4615    ev |= GetBitFields(p_GetExp(p, j,r), i, n);
4616    i += n;
4617    j++;
4618  }
4619  return ev;
4620}
4621
4622
4623unsigned long p_GetShortExpVector(const poly p, const poly pp, const ring r)
4624{
4625  assume(p != NULL);
4626  assume(pp != NULL);
4627  if (p == NULL || pp == NULL) return 0;
4628 
4629  unsigned long ev = 0; // short exponent vector
4630  unsigned int n = BIT_SIZEOF_LONG / r->N; // number of bits per exp
4631  unsigned int m1; // highest bit which is filled with (n+1)
4632  unsigned int i = 0, j=1;
4633
4634  if (n == 0)
4635  {
4636    if (r->N <2*BIT_SIZEOF_LONG)
4637    {
4638      n=1;
4639      m1=0;
4640    }
4641    else
4642    {
4643      for (; j<=(unsigned long) r->N; j++)
4644      {
4645        if (p_GetExp(p,j,r) > 0 || p_GetExp(pp,j,r) > 0) i++;
4646        if (i == BIT_SIZEOF_LONG) break;
4647      }
4648      if (i>0)
4649        ev = ~((unsigned long)0) >> ((unsigned long) (BIT_SIZEOF_LONG - i));
4650      return ev;
4651    }
4652  }
4653  else
4654  {
4655    m1 = (n+1)*(BIT_SIZEOF_LONG - n*r->N);
4656  }
4657
4658  n++;
4659  while (i<m1)
4660  {
4661    ev |= GetBitFields(p_GetExp(p, j,r) + p_GetExp(pp, j,r), i, n);
4662    i += n;
4663    j++;
4664  }
4665
4666  n--;
4667  while (i<BIT_SIZEOF_LONG)
4668  {
4669    ev |= GetBitFields(p_GetExp(p, j,r) + p_GetExp(pp, j,r), i, n);
4670    i += n;
4671    j++;
4672  }
4673  return ev;
4674}
4675
4676
4677
4678/***************************************************************
4679 *
4680 * p_ShallowDelete
4681 *
4682 ***************************************************************/
4683#undef LINKAGE
4684#define LINKAGE
4685#undef p_Delete__T
4686#define p_Delete__T p_ShallowDelete
4687#undef n_Delete__T
4688#define n_Delete__T(n, r) do {} while (0)
4689
4690#include <polys/templates/p_Delete__T.cc>
4691
Note: See TracBrowser for help on using the repository browser.