source: git/libpolys/polys/monomials/p_polys.cc @ 4a45a4e

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