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

spielwiese
Last change on this file since fd07781 was fd07781, checked in by Hans Schoenemann <hannes@…>, 9 years ago
optimize p_Size
  • Property mode set to 100644
File size: 97.8 KB
Line 
1/****************************************
2*  Computer Algebra System SINGULAR     *
3****************************************/
4/***************************************************************
5 *  File:    p_polys.cc
6 *  Purpose: implementation of ring independent poly procedures?
7 *  Author:  obachman (Olaf Bachmann)
8 *  Created: 8/00
9 *******************************************************************/
10
11#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(h,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  if (r->cf->has_simple_Alloc)
3098    return pLength(p);
3099  while ( p != NULL )
3100  {
3101    count+= n_Size( pGetCoeff( p ), r->cf );
3102    pIter( p );
3103  }
3104  return count;
3105}
3106
3107/*2
3108*make p homogeneous by multiplying the monomials by powers of x_varnum
3109*assume: deg(var(varnum))==1
3110*/
3111poly p_Homogen (poly p, int varnum, const ring r)
3112{
3113  pFDegProc deg;
3114  if (r->pLexOrder && (r->order[0]==ringorder_lp))
3115    deg=p_Totaldegree;
3116  else
3117    deg=r->pFDeg;
3118
3119  poly q=NULL, qn;
3120  int  o,ii;
3121  sBucket_pt bp;
3122
3123  if (p!=NULL)
3124  {
3125    if ((varnum < 1) || (varnum > rVar(r)))
3126    {
3127      return NULL;
3128    }
3129    o=deg(p,r);
3130    q=pNext(p);
3131    while (q != NULL)
3132    {
3133      ii=deg(q,r);
3134      if (ii>o) o=ii;
3135      pIter(q);
3136    }
3137    q = p_Copy(p,r);
3138    bp = sBucketCreate(r);
3139    while (q != NULL)
3140    {
3141      ii = o-deg(q,r);
3142      if (ii!=0)
3143      {
3144        p_AddExp(q,varnum, (long)ii,r);
3145        p_Setm(q,r);
3146      }
3147      qn = pNext(q);
3148      pNext(q) = NULL;
3149      sBucket_Add_p(bp, q, 1);
3150      q = qn;
3151    }
3152    sBucketDestroyAdd(bp, &q, &ii);
3153  }
3154  return q;
3155}
3156
3157/*2
3158*tests if p is homogeneous with respect to the actual weigths
3159*/
3160BOOLEAN p_IsHomogeneous (poly p, const ring r)
3161{
3162  poly qp=p;
3163  int o;
3164
3165  if ((p == NULL) || (pNext(p) == NULL)) return TRUE;
3166  pFDegProc d;
3167  if (r->pLexOrder && (r->order[0]==ringorder_lp))
3168    d=p_Totaldegree;
3169  else
3170    d=r->pFDeg;
3171  o = d(p,r);
3172  do
3173  {
3174    if (d(qp,r) != o) return FALSE;
3175    pIter(qp);
3176  }
3177  while (qp != NULL);
3178  return TRUE;
3179}
3180
3181/*----------utilities for syzygies--------------*/
3182BOOLEAN   p_VectorHasUnitB(poly p, int * k, const ring r)
3183{
3184  poly q=p,qq;
3185  int i;
3186
3187  while (q!=NULL)
3188  {
3189    if (p_LmIsConstantComp(q,r))
3190    {
3191      i = p_GetComp(q,r);
3192      qq = p;
3193      while ((qq != q) && (p_GetComp(qq,r) != i)) pIter(qq);
3194      if (qq == q)
3195      {
3196        *k = i;
3197        return TRUE;
3198      }
3199      else
3200        pIter(q);
3201    }
3202    else pIter(q);
3203  }
3204  return FALSE;
3205}
3206
3207void   p_VectorHasUnit(poly p, int * k, int * len, const ring r)
3208{
3209  poly q=p,qq;
3210  int i,j=0;
3211
3212  *len = 0;
3213  while (q!=NULL)
3214  {
3215    if (p_LmIsConstantComp(q,r))
3216    {
3217      i = p_GetComp(q,r);
3218      qq = p;
3219      while ((qq != q) && (p_GetComp(qq,r) != i)) pIter(qq);
3220      if (qq == q)
3221      {
3222       j = 0;
3223       while (qq!=NULL)
3224       {
3225         if (p_GetComp(qq,r)==i) j++;
3226        pIter(qq);
3227       }
3228       if ((*len == 0) || (j<*len))
3229       {
3230         *len = j;
3231         *k = i;
3232       }
3233      }
3234    }
3235    pIter(q);
3236  }
3237}
3238
3239poly p_TakeOutComp1(poly * p, int k, const ring r)
3240{
3241  poly q = *p;
3242
3243  if (q==NULL) return NULL;
3244
3245  poly qq=NULL,result = NULL;
3246
3247  if (p_GetComp(q,r)==k)
3248  {
3249    result = q; /* *p */
3250    while ((q!=NULL) && (p_GetComp(q,r)==k))
3251    {
3252      p_SetComp(q,0,r);
3253      p_SetmComp(q,r);
3254      qq = q;
3255      pIter(q);
3256    }
3257    *p = q;
3258    pNext(qq) = NULL;
3259  }
3260  if (q==NULL) return result;
3261//  if (pGetComp(q) > k) pGetComp(q)--;
3262  while (pNext(q)!=NULL)
3263  {
3264    if (p_GetComp(pNext(q),r)==k)
3265    {
3266      if (result==NULL)
3267      {
3268        result = pNext(q);
3269        qq = result;
3270      }
3271      else
3272      {
3273        pNext(qq) = pNext(q);
3274        pIter(qq);
3275      }
3276      pNext(q) = pNext(pNext(q));
3277      pNext(qq) =NULL;
3278      p_SetComp(qq,0,r);
3279      p_SetmComp(qq,r);
3280    }
3281    else
3282    {
3283      pIter(q);
3284//      if (pGetComp(q) > k) pGetComp(q)--;
3285    }
3286  }
3287  return result;
3288}
3289
3290poly p_TakeOutComp(poly * p, int k, const ring r)
3291{
3292  poly q = *p,qq=NULL,result = NULL;
3293
3294  if (q==NULL) return NULL;
3295  BOOLEAN use_setmcomp=rOrd_SetCompRequiresSetm(r);
3296  if (p_GetComp(q,r)==k)
3297  {
3298    result = q;
3299    do
3300    {
3301      p_SetComp(q,0,r);
3302      if (use_setmcomp) p_SetmComp(q,r);
3303      qq = q;
3304      pIter(q);
3305    }
3306    while ((q!=NULL) && (p_GetComp(q,r)==k));
3307    *p = q;
3308    pNext(qq) = NULL;
3309  }
3310  if (q==NULL) return result;
3311  if (p_GetComp(q,r) > k)
3312  {
3313    p_SubComp(q,1,r);
3314    if (use_setmcomp) p_SetmComp(q,r);
3315  }
3316  poly pNext_q;
3317  while ((pNext_q=pNext(q))!=NULL)
3318  {
3319    if (p_GetComp(pNext_q,r)==k)
3320    {
3321      if (result==NULL)
3322      {
3323        result = pNext_q;
3324        qq = result;
3325      }
3326      else
3327      {
3328        pNext(qq) = pNext_q;
3329        pIter(qq);
3330      }
3331      pNext(q) = pNext(pNext_q);
3332      pNext(qq) =NULL;
3333      p_SetComp(qq,0,r);
3334      if (use_setmcomp) p_SetmComp(qq,r);
3335    }
3336    else
3337    {
3338      /*pIter(q);*/ q=pNext_q;
3339      if (p_GetComp(q,r) > k)
3340      {
3341        p_SubComp(q,1,r);
3342        if (use_setmcomp) p_SetmComp(q,r);
3343      }
3344    }
3345  }
3346  return result;
3347}
3348
3349// Splits *p into two polys: *q which consists of all monoms with
3350// component == comp and *p of all other monoms *lq == pLength(*q)
3351void p_TakeOutComp(poly *r_p, long comp, poly *r_q, int *lq, const ring r)
3352{
3353  spolyrec pp, qq;
3354  poly p, q, p_prev;
3355  int l = 0;
3356
3357#ifdef HAVE_ASSUME
3358  int lp = pLength(*r_p);
3359#endif
3360
3361  pNext(&pp) = *r_p;
3362  p = *r_p;
3363  p_prev = &pp;
3364  q = &qq;
3365
3366  while(p != NULL)
3367  {
3368    while (p_GetComp(p,r) == comp)
3369    {
3370      pNext(q) = p;
3371      pIter(q);
3372      p_SetComp(p, 0,r);
3373      p_SetmComp(p,r);
3374      pIter(p);
3375      l++;
3376      if (p == NULL)
3377      {
3378        pNext(p_prev) = NULL;
3379        goto Finish;
3380      }
3381    }
3382    pNext(p_prev) = p;
3383    p_prev = p;
3384    pIter(p);
3385  }
3386
3387  Finish:
3388  pNext(q) = NULL;
3389  *r_p = pNext(&pp);
3390  *r_q = pNext(&qq);
3391  *lq = l;
3392#ifdef HAVE_ASSUME
3393  assume(pLength(*r_p) + pLength(*r_q) == lp);
3394#endif
3395  p_Test(*r_p,r);
3396  p_Test(*r_q,r);
3397}
3398
3399void p_DeleteComp(poly * p,int k, const ring r)
3400{
3401  poly q;
3402
3403  while ((*p!=NULL) && (p_GetComp(*p,r)==k)) p_LmDelete(p,r);
3404  if (*p==NULL) return;
3405  q = *p;
3406  if (p_GetComp(q,r)>k)
3407  {
3408    p_SubComp(q,1,r);
3409    p_SetmComp(q,r);
3410  }
3411  while (pNext(q)!=NULL)
3412  {
3413    if (p_GetComp(pNext(q),r)==k)
3414      p_LmDelete(&(pNext(q)),r);
3415    else
3416    {
3417      pIter(q);
3418      if (p_GetComp(q,r)>k)
3419      {
3420        p_SubComp(q,1,r);
3421        p_SetmComp(q,r);
3422      }
3423    }
3424  }
3425}
3426
3427/*2
3428* convert a vector to a set of polys,
3429* allocates the polyset, (entries 0..(*len)-1)
3430* the vector will not be changed
3431*/
3432void  p_Vec2Polys(poly v, poly* *p, int *len, const ring r)
3433{
3434  poly h;
3435  int k;
3436
3437  *len=p_MaxComp(v,r);
3438  if (*len==0) *len=1;
3439  *p=(poly*)omAlloc0((*len)*sizeof(poly));
3440  while (v!=NULL)
3441  {
3442    h=p_Head(v,r);
3443    k=p_GetComp(h,r);
3444    p_SetComp(h,0,r);
3445    (*p)[k-1]=p_Add_q((*p)[k-1],h,r);
3446    pIter(v);
3447  }
3448}
3449
3450//
3451// resets the pFDeg and pLDeg: if pLDeg is not given, it is
3452// set to currRing->pLDegOrig, i.e. to the respective LDegProc which
3453// only uses pFDeg (and not p_Deg, or pTotalDegree, etc)
3454void pSetDegProcs(ring r, pFDegProc new_FDeg, pLDegProc new_lDeg)
3455{
3456  assume(new_FDeg != NULL);
3457  r->pFDeg = new_FDeg;
3458
3459  if (new_lDeg == NULL)
3460    new_lDeg = r->pLDegOrig;
3461
3462  r->pLDeg = new_lDeg;
3463}
3464
3465// restores pFDeg and pLDeg:
3466void pRestoreDegProcs(ring r, pFDegProc old_FDeg, pLDegProc old_lDeg)
3467{
3468  assume(old_FDeg != NULL && old_lDeg != NULL);
3469  r->pFDeg = old_FDeg;
3470  r->pLDeg = old_lDeg;
3471}
3472
3473/*-------- several access procedures to monomials -------------------- */
3474/*
3475* the module weights for std
3476*/
3477static pFDegProc pOldFDeg;
3478static pLDegProc pOldLDeg;
3479static BOOLEAN pOldLexOrder;
3480
3481static long pModDeg(poly p, ring r)
3482{
3483  long d=pOldFDeg(p, r);
3484  int c=p_GetComp(p, r);
3485  if ((c>0) && ((r->pModW)->range(c-1))) d+= (*(r->pModW))[c-1];
3486  return d;
3487  //return pOldFDeg(p, r)+(*pModW)[p_GetComp(p, r)-1];
3488}
3489
3490void p_SetModDeg(intvec *w, ring r)
3491{
3492  if (w!=NULL)
3493  {
3494    r->pModW = w;
3495    pOldFDeg = r->pFDeg;
3496    pOldLDeg = r->pLDeg;
3497    pOldLexOrder = r->pLexOrder;
3498    pSetDegProcs(r,pModDeg);
3499    r->pLexOrder = TRUE;
3500  }
3501  else
3502  {
3503    r->pModW = NULL;
3504    pRestoreDegProcs(r,pOldFDeg, pOldLDeg);
3505    r->pLexOrder = pOldLexOrder;
3506  }
3507}
3508
3509/*2
3510* handle memory request for sets of polynomials (ideals)
3511* l is the length of *p, increment is the difference (may be negative)
3512*/
3513void pEnlargeSet(poly* *p, int l, int increment)
3514{
3515  poly* h;
3516
3517  if (*p==NULL)
3518  {
3519    if (increment==0) return;
3520    h=(poly*)omAlloc0(increment*sizeof(poly));
3521  }
3522  else
3523  {
3524    h=(poly*)omReallocSize((poly*)*p,l*sizeof(poly),(l+increment)*sizeof(poly));
3525    if (increment>0)
3526    {
3527      //for (i=l; i<l+increment; i++)
3528      //  h[i]=NULL;
3529      memset(&(h[l]),0,increment*sizeof(poly));
3530    }
3531  }
3532  *p=h;
3533}
3534
3535/*2
3536*divides p1 by its leading coefficient
3537*/
3538void p_Norm(poly p1, const ring r)
3539{
3540#ifdef HAVE_RINGS
3541  if (rField_is_Ring(r))
3542  {
3543    if (!n_IsUnit(pGetCoeff(p1), r->cf)) return;
3544    // Werror("p_Norm not possible in the case of coefficient rings.");
3545  }
3546  else
3547#endif
3548  if (p1!=NULL)
3549  {
3550    if (pNext(p1)==NULL)
3551    {
3552      p_SetCoeff(p1,n_Init(1,r->cf),r);
3553      return;
3554    }
3555    poly h;
3556    if (!n_IsOne(pGetCoeff(p1),r->cf))
3557    {
3558      number k, c;
3559      n_Normalize(pGetCoeff(p1),r->cf);
3560      k = pGetCoeff(p1);
3561      c = n_Init(1,r->cf);
3562      pSetCoeff0(p1,c);
3563      h = pNext(p1);
3564      while (h!=NULL)
3565      {
3566        c=n_Div(pGetCoeff(h),k,r->cf);
3567        // no need to normalize: Z/p, R
3568        // normalize already in nDiv: Q_a, Z/p_a
3569        // remains: Q
3570        if (rField_is_Q(r) && (!n_IsOne(c,r->cf))) n_Normalize(c,r->cf);
3571        p_SetCoeff(h,c,r);
3572        pIter(h);
3573      }
3574      n_Delete(&k,r->cf);
3575    }
3576    else
3577    {
3578      //if (r->cf->cfNormalize != nDummy2) //TODO: OPTIMIZE
3579      {
3580        h = pNext(p1);
3581        while (h!=NULL)
3582        {
3583          n_Normalize(pGetCoeff(h),r->cf);
3584          pIter(h);
3585        }
3586      }
3587    }
3588  }
3589}
3590
3591/*2
3592*normalize all coefficients
3593*/
3594void p_Normalize(poly p,const ring r)
3595{
3596  if (rField_has_simple_inverse(r)) return; /* Z/p, GF(p,n), R, long R/C */
3597  while (p!=NULL)
3598  {
3599#ifdef LDEBUG
3600    n_Test(pGetCoeff(p), r->cf);
3601#endif
3602    n_Normalize(pGetCoeff(p),r->cf);
3603    pIter(p);
3604  }
3605}
3606
3607// splits p into polys with Exp(n) == 0 and Exp(n) != 0
3608// Poly with Exp(n) != 0 is reversed
3609static void p_SplitAndReversePoly(poly p, int n, poly *non_zero, poly *zero, const ring r)
3610{
3611  if (p == NULL)
3612  {
3613    *non_zero = NULL;
3614    *zero = NULL;
3615    return;
3616  }
3617  spolyrec sz;
3618  poly z, n_z, next;
3619  z = &sz;
3620  n_z = NULL;
3621
3622  while(p != NULL)
3623  {
3624    next = pNext(p);
3625    if (p_GetExp(p, n,r) == 0)
3626    {
3627      pNext(z) = p;
3628      pIter(z);
3629    }
3630    else
3631    {
3632      pNext(p) = n_z;
3633      n_z = p;
3634    }
3635    p = next;
3636  }
3637  pNext(z) = NULL;
3638  *zero = pNext(&sz);
3639  *non_zero = n_z;
3640}
3641/*3
3642* substitute the n-th variable by 1 in p
3643* destroy p
3644*/
3645static poly p_Subst1 (poly p,int n, const ring r)
3646{
3647  poly qq=NULL, result = NULL;
3648  poly zero=NULL, non_zero=NULL;
3649
3650  // reverse, so that add is likely to be linear
3651  p_SplitAndReversePoly(p, n, &non_zero, &zero,r);
3652
3653  while (non_zero != NULL)
3654  {
3655    assume(p_GetExp(non_zero, n,r) != 0);
3656    qq = non_zero;
3657    pIter(non_zero);
3658    qq->next = NULL;
3659    p_SetExp(qq,n,0,r);
3660    p_Setm(qq,r);
3661    result = p_Add_q(result,qq,r);
3662  }
3663  p = p_Add_q(result, zero,r);
3664  p_Test(p,r);
3665  return p;
3666}
3667
3668/*3
3669* substitute the n-th variable by number e in p
3670* destroy p
3671*/
3672static poly p_Subst2 (poly p,int n, number e, const ring r)
3673{
3674  assume( ! n_IsZero(e,r->cf) );
3675  poly qq,result = NULL;
3676  number nn, nm;
3677  poly zero, non_zero;
3678
3679  // reverse, so that add is likely to be linear
3680  p_SplitAndReversePoly(p, n, &non_zero, &zero,r);
3681
3682  while (non_zero != NULL)
3683  {
3684    assume(p_GetExp(non_zero, n, r) != 0);
3685    qq = non_zero;
3686    pIter(non_zero);
3687    qq->next = NULL;
3688    n_Power(e, p_GetExp(qq, n, r), &nn,r->cf);
3689    nm = n_Mult(nn, pGetCoeff(qq),r->cf);
3690#ifdef HAVE_RINGS
3691    if (n_IsZero(nm,r->cf))
3692    {
3693      p_LmFree(&qq,r);
3694      n_Delete(&nm,r->cf);
3695    }
3696    else
3697#endif
3698    {
3699      p_SetCoeff(qq, nm,r);
3700      p_SetExp(qq, n, 0,r);
3701      p_Setm(qq,r);
3702      result = p_Add_q(result,qq,r);
3703    }
3704    n_Delete(&nn,r->cf);
3705  }
3706  p = p_Add_q(result, zero,r);
3707  p_Test(p,r);
3708  return p;
3709}
3710
3711
3712/* delete monoms whose n-th exponent is different from zero */
3713static poly p_Subst0(poly p, int n, const ring r)
3714{
3715  spolyrec res;
3716  poly h = &res;
3717  pNext(h) = p;
3718
3719  while (pNext(h)!=NULL)
3720  {
3721    if (p_GetExp(pNext(h),n,r)!=0)
3722    {
3723      p_LmDelete(&pNext(h),r);
3724    }
3725    else
3726    {
3727      pIter(h);
3728    }
3729  }
3730  p_Test(pNext(&res),r);
3731  return pNext(&res);
3732}
3733
3734/*2
3735* substitute the n-th variable by e in p
3736* destroy p
3737*/
3738poly p_Subst(poly p, int n, poly e, const ring r)
3739{
3740  if (e == NULL) return p_Subst0(p, n,r);
3741
3742  if (p_IsConstant(e,r))
3743  {
3744    if (n_IsOne(pGetCoeff(e),r->cf)) return p_Subst1(p,n,r);
3745    else return p_Subst2(p, n, pGetCoeff(e),r);
3746  }
3747
3748#ifdef HAVE_PLURAL
3749  if (rIsPluralRing(r))
3750  {
3751    return nc_pSubst(p,n,e,r);
3752  }
3753#endif
3754
3755  int exponent,i;
3756  poly h, res, m;
3757  int *me,*ee;
3758  number nu,nu1;
3759
3760  me=(int *)omAlloc((rVar(r)+1)*sizeof(int));
3761  ee=(int *)omAlloc((rVar(r)+1)*sizeof(int));
3762  if (e!=NULL) p_GetExpV(e,ee,r);
3763  res=NULL;
3764  h=p;
3765  while (h!=NULL)
3766  {
3767    if ((e!=NULL) || (p_GetExp(h,n,r)==0))
3768    {
3769      m=p_Head(h,r);
3770      p_GetExpV(m,me,r);
3771      exponent=me[n];
3772      me[n]=0;
3773      for(i=rVar(r);i>0;i--)
3774        me[i]+=exponent*ee[i];
3775      p_SetExpV(m,me,r);
3776      if (e!=NULL)
3777      {
3778        n_Power(pGetCoeff(e),exponent,&nu,r->cf);
3779        nu1=n_Mult(pGetCoeff(m),nu,r->cf);
3780        n_Delete(&nu,r->cf);
3781        p_SetCoeff(m,nu1,r);
3782      }
3783      res=p_Add_q(res,m,r);
3784    }
3785    p_LmDelete(&h,r);
3786  }
3787  omFreeSize((ADDRESS)me,(rVar(r)+1)*sizeof(int));
3788  omFreeSize((ADDRESS)ee,(rVar(r)+1)*sizeof(int));
3789  return res;
3790}
3791
3792/*2
3793 * returns a re-ordered convertion of a number as a polynomial,
3794 * with permutation of parameters
3795 * NOTE: this only works for Frank's alg. & trans. fields
3796 */
3797poly n_PermNumber(const number z, const int *par_perm, const int , const ring src, const ring dst)
3798{
3799#if 0
3800  PrintS("\nSource Ring: \n");
3801  rWrite(src);
3802
3803  if(0)
3804  {
3805    number zz = n_Copy(z, src->cf);
3806    PrintS("z: "); n_Write(zz, src);
3807    n_Delete(&zz, src->cf);
3808  }
3809
3810  PrintS("\nDestination Ring: \n");
3811  rWrite(dst);
3812
3813  /*Print("\nOldPar: %d\n", OldPar);
3814  for( int i = 1; i <= OldPar; i++ )
3815  {
3816    Print("par(%d) -> par/var (%d)\n", i, par_perm[i-1]);
3817  }*/
3818#endif
3819  if( z == NULL )
3820     return NULL;
3821
3822  const coeffs srcCf = src->cf;
3823  assume( srcCf != NULL );
3824
3825  assume( !nCoeff_is_GF(srcCf) );
3826  assume( src->cf->extRing!=NULL );
3827
3828  poly zz = NULL;
3829
3830  const ring srcExtRing = srcCf->extRing;
3831  assume( srcExtRing != NULL );
3832
3833  const coeffs dstCf = dst->cf;
3834  assume( dstCf != NULL );
3835
3836  if( nCoeff_is_algExt(srcCf) ) // nCoeff_is_GF(srcCf)?
3837  {
3838    zz = (poly) z;
3839    if( zz == NULL ) return NULL;
3840  }
3841  else if (nCoeff_is_transExt(srcCf))
3842  {
3843    assume( !IS0(z) );
3844
3845    zz = NUM((fraction)z);
3846    p_Test (zz, srcExtRing);
3847
3848    if( zz == NULL ) return NULL;
3849    if( !DENIS1((fraction)z) )
3850    {
3851      if (!p_IsConstant(DEN((fraction)z),srcExtRing))
3852        WarnS("Not defined: Cannot map a rational fraction and make a polynomial out of it! Ignoring the denumerator.");
3853    }
3854  }
3855  else
3856  {
3857    assume (FALSE);
3858    Werror("Number permutation is not implemented for this data yet!");
3859    return NULL;
3860  }
3861
3862  assume( zz != NULL );
3863  p_Test (zz, srcExtRing);
3864
3865  nMapFunc nMap = n_SetMap(srcExtRing->cf, dstCf);
3866
3867  assume( nMap != NULL );
3868
3869  poly qq;
3870  if ((par_perm == NULL) && (rPar(dst) != 0 && rVar (srcExtRing) > 0))
3871  {
3872    int* perm;
3873    perm=(int *)omAlloc0((rVar(srcExtRing)+1)*sizeof(int));
3874    perm[0]= 0;
3875    for(int i=si_min(rVar(srcExtRing),rPar(dst));i>0;i--)
3876      perm[i]=-i;
3877    qq = p_PermPoly(zz, perm, srcExtRing, dst, nMap, NULL, rVar(srcExtRing)-1);
3878    omFreeSize ((ADDRESS)perm, (rVar(srcExtRing)+1)*sizeof(int));
3879  }
3880  else
3881    qq = p_PermPoly(zz, par_perm-1, srcExtRing, dst, nMap, NULL, rVar (srcExtRing)-1);
3882
3883  if(nCoeff_is_transExt(srcCf)
3884  && (!DENIS1((fraction)z))
3885  && p_IsConstant(DEN((fraction)z),srcExtRing))
3886  {
3887    number n=nMap(pGetCoeff(DEN((fraction)z)),srcExtRing->cf, dstCf);
3888    qq=p_Div_nn(qq,n,dst);
3889    n_Delete(&n,dstCf);
3890    p_Normalize(qq,dst);
3891  }
3892  p_Test (qq, dst);
3893
3894  return qq;
3895}
3896
3897
3898/*2
3899*returns a re-ordered copy of a polynomial, with permutation of the variables
3900*/
3901poly p_PermPoly (poly p, const int * perm, const ring oldRing, const ring dst,
3902       nMapFunc nMap, const int *par_perm, int OldPar)
3903{
3904#if 0
3905    p_Test(p, oldRing);
3906    PrintS("\np_PermPoly::p: "); p_Write(p, oldRing, oldRing); PrintLn();
3907#endif
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  assume(dst != NULL);
3914  assume(dst->cf != NULL);
3915  while (p != NULL)
3916  {
3917    // map the coefficient
3918    if ( ((OldPar == 0) || (par_perm == NULL) || rField_is_GF(oldRing)) && (nMap != NULL) )
3919    {
3920      qq = p_Init(dst);
3921      assume( nMap != NULL );
3922      number n = nMap(p_GetCoeff(p, oldRing), oldRing->cf, dst->cf);
3923      n_Test (n,dst->cf);
3924      if ( nCoeff_is_algExt(dst->cf) )
3925        n_Normalize(n, dst->cf);
3926      p_GetCoeff(qq, dst) = n;// Note: n can be a ZERO!!!
3927    }
3928    else
3929    {
3930      qq = p_One(dst);
3931//      aq = naPermNumber(p_GetCoeff(p, oldRing), par_perm, OldPar, oldRing); // no dst???
3932//      poly    n_PermNumber(const number z, const int *par_perm, const int P, const ring src, const ring dst)
3933      aq = n_PermNumber(p_GetCoeff(p, oldRing), par_perm, OldPar, oldRing, dst);
3934      p_Test(aq, dst);
3935      if ( nCoeff_is_algExt(dst->cf) )
3936        p_Normalize(aq,dst);
3937      if (aq == NULL)
3938        p_SetCoeff(qq, n_Init(0, dst->cf),dst); // Very dirty trick!!!
3939      p_Test(aq, dst);
3940    }
3941    if (rRing_has_Comp(dst))
3942       p_SetComp(qq, p_GetComp(p, oldRing), dst);
3943    if ( n_IsZero(pGetCoeff(qq), dst->cf) )
3944    {
3945      p_LmDelete(&qq,dst);
3946      qq = NULL;
3947    }
3948    else
3949    {
3950      // map pars:
3951      int mapped_to_par = 0;
3952      for(int i = 1; i <= OldpVariables; i++)
3953      {
3954        int e = p_GetExp(p, i, oldRing);
3955        if (e != 0)
3956        {
3957          if (perm==NULL)
3958            p_SetExp(qq, i, e, dst);
3959          else if (perm[i]>0)
3960            p_AddExp(qq,perm[i], e/*p_GetExp( p,i,oldRing)*/, dst);
3961          else if (perm[i]<0)
3962          {
3963            number c = p_GetCoeff(qq, dst);
3964            if (rField_is_GF(dst))
3965            {
3966              assume( dst->cf->extRing == NULL );
3967              number ee = n_Param(1, dst);
3968              number eee;
3969              n_Power(ee, e, &eee, dst->cf); //nfDelete(ee,dst);
3970              ee = n_Mult(c, eee, dst->cf);
3971              //nfDelete(c,dst);nfDelete(eee,dst);
3972              pSetCoeff0(qq,ee);
3973            }
3974            else if (nCoeff_is_Extension(dst->cf))
3975            {
3976              const int par = -perm[i];
3977              assume( par > 0 );
3978//              WarnS("longalg missing 3");
3979#if 1
3980              const coeffs C = dst->cf;
3981              assume( C != NULL );
3982              const ring R = C->extRing;
3983              assume( R != NULL );
3984              assume( par <= rVar(R) );
3985              poly pcn; // = (number)c
3986              assume( !n_IsZero(c, C) );
3987              if( nCoeff_is_algExt(C) )
3988                 pcn = (poly) c;
3989               else //            nCoeff_is_transExt(C)
3990                 pcn = NUM((fraction)c);
3991              if (pNext(pcn) == NULL) // c->z
3992                p_AddExp(pcn, -perm[i], e, R);
3993              else /* more difficult: we have really to multiply: */
3994              {
3995                poly mmc = p_ISet(1, R);
3996                p_SetExp(mmc, -perm[i], e, R);
3997                p_Setm(mmc, R);
3998                number nnc;
3999                // convert back to a number: number nnc = mmc;
4000                if( nCoeff_is_algExt(C) )
4001                   nnc = (number) mmc;
4002                else //            nCoeff_is_transExt(C)
4003                  nnc = ntInit(mmc, C);
4004                p_GetCoeff(qq, dst) = n_Mult((number)c, nnc, C);
4005                n_Delete((number *)&c, C);
4006                n_Delete((number *)&nnc, C);
4007              }
4008              mapped_to_par=1;
4009#endif
4010            }
4011          }
4012          else
4013          {
4014            /* this variable maps to 0 !*/
4015            p_LmDelete(&qq, dst);
4016            break;
4017          }
4018        }
4019      }
4020      if ( mapped_to_par && qq!= NULL && nCoeff_is_algExt(dst->cf) )
4021      {
4022        number n = p_GetCoeff(qq, dst);
4023        n_Normalize(n, dst->cf);
4024        p_GetCoeff(qq, dst) = n;
4025      }
4026    }
4027    pIter(p);
4028
4029#if 0
4030    p_Test(aq,dst);
4031    PrintS("\naq: "); p_Write(aq, dst, dst); PrintLn();
4032#endif
4033
4034
4035#if 1
4036    if (qq!=NULL)
4037    {
4038      p_Setm(qq,dst);
4039
4040      p_Test(aq,dst);
4041      p_Test(qq,dst);
4042
4043#if 0
4044    p_Test(qq,dst);
4045    PrintS("\nqq: "); p_Write(qq, dst, dst); PrintLn();
4046#endif
4047
4048      if (aq!=NULL)
4049         qq=p_Mult_q(aq,qq,dst);
4050      aq = qq;
4051      while (pNext(aq) != NULL) pIter(aq);
4052      if (result_last==NULL)
4053      {
4054        result=qq;
4055      }
4056      else
4057      {
4058        pNext(result_last)=qq;
4059      }
4060      result_last=aq;
4061      aq = NULL;
4062    }
4063    else if (aq!=NULL)
4064    {
4065      p_Delete(&aq,dst);
4066    }
4067  }
4068  result=p_SortAdd(result,dst);
4069#else
4070  //  if (qq!=NULL)
4071  //  {
4072  //    pSetm(qq);
4073  //    pTest(qq);
4074  //    pTest(aq);
4075  //    if (aq!=NULL) qq=pMult(aq,qq);
4076  //    aq = qq;
4077  //    while (pNext(aq) != NULL) pIter(aq);
4078  //    pNext(aq) = result;
4079  //    aq = NULL;
4080  //    result = qq;
4081  //  }
4082  //  else if (aq!=NULL)
4083  //  {
4084  //    pDelete(&aq);
4085  //  }
4086  //}
4087  //p = result;
4088  //result = NULL;
4089  //while (p != NULL)
4090  //{
4091  //  qq = p;
4092  //  pIter(p);
4093  //  qq->next = NULL;
4094  //  result = pAdd(result, qq);
4095  //}
4096#endif
4097  p_Test(result,dst);
4098#if 0
4099  p_Test(result,dst);
4100  PrintS("\nresult: "); p_Write(result,dst,dst); PrintLn();
4101#endif
4102  return result;
4103}
4104/**************************************************************
4105 *
4106 * Jet
4107 *
4108 **************************************************************/
4109
4110poly pp_Jet(poly p, int m, const ring R)
4111{
4112  poly r=NULL;
4113  poly t=NULL;
4114
4115  while (p!=NULL)
4116  {
4117    if (p_Totaldegree(p,R)<=m)
4118    {
4119      if (r==NULL)
4120        r=p_Head(p,R);
4121      else
4122      if (t==NULL)
4123      {
4124        pNext(r)=p_Head(p,R);
4125        t=pNext(r);
4126      }
4127      else
4128      {
4129        pNext(t)=p_Head(p,R);
4130        pIter(t);
4131      }
4132    }
4133    pIter(p);
4134  }
4135  return r;
4136}
4137
4138poly p_Jet(poly p, int m,const ring R)
4139{
4140  while((p!=NULL) && (p_Totaldegree(p,R)>m)) p_LmDelete(&p,R);
4141  if (p==NULL) return NULL;
4142  poly r=p;
4143  while (pNext(p)!=NULL)
4144  {
4145    if (p_Totaldegree(pNext(p),R)>m)
4146    {
4147      p_LmDelete(&pNext(p),R);
4148    }
4149    else
4150      pIter(p);
4151  }
4152  return r;
4153}
4154
4155poly pp_JetW(poly p, int m, short *w, const ring R)
4156{
4157  poly r=NULL;
4158  poly t=NULL;
4159  while (p!=NULL)
4160  {
4161    if (totaldegreeWecart_IV(p,R,w)<=m)
4162    {
4163      if (r==NULL)
4164        r=p_Head(p,R);
4165      else
4166      if (t==NULL)
4167      {
4168        pNext(r)=p_Head(p,R);
4169        t=pNext(r);
4170      }
4171      else
4172      {
4173        pNext(t)=p_Head(p,R);
4174        pIter(t);
4175      }
4176    }
4177    pIter(p);
4178  }
4179  return r;
4180}
4181
4182poly p_JetW(poly p, int m, short *w, const ring R)
4183{
4184  while((p!=NULL) && (totaldegreeWecart_IV(p,R,w)>m)) p_LmDelete(&p,R);
4185  if (p==NULL) return NULL;
4186  poly r=p;
4187  while (pNext(p)!=NULL)
4188  {
4189    if (totaldegreeWecart_IV(pNext(p),R,w)>m)
4190    {
4191      p_LmDelete(&pNext(p),R);
4192    }
4193    else
4194      pIter(p);
4195  }
4196  return r;
4197}
4198
4199/*************************************************************/
4200int p_MinDeg(poly p,intvec *w, const ring R)
4201{
4202  if(p==NULL)
4203    return -1;
4204  int d=-1;
4205  while(p!=NULL)
4206  {
4207    int d0=0;
4208    for(int j=0;j<rVar(R);j++)
4209      if(w==NULL||j>=w->length())
4210        d0+=p_GetExp(p,j+1,R);
4211      else
4212        d0+=(*w)[j]*p_GetExp(p,j+1,R);
4213    if(d0<d||d==-1)
4214      d=d0;
4215    pIter(p);
4216  }
4217  return d;
4218}
4219
4220/***************************************************************/
4221
4222poly p_Series(int n,poly p,poly u, intvec *w, const ring R)
4223{
4224  short *ww=iv2array(w,R);
4225  if(p!=NULL)
4226  {
4227    if(u==NULL)
4228      p=p_JetW(p,n,ww,R);
4229    else
4230      p=p_JetW(p_Mult_q(p,p_Invers(n-p_MinDeg(p,w,R),u,w,R),R),n,ww,R);
4231  }
4232  omFreeSize((ADDRESS)ww,(rVar(R)+1)*sizeof(short));
4233  return p;
4234}
4235
4236poly p_Invers(int n,poly u,intvec *w, const ring R)
4237{
4238  if(n<0)
4239    return NULL;
4240  number u0=n_Invers(pGetCoeff(u),R->cf);
4241  poly v=p_NSet(u0,R);
4242  if(n==0)
4243    return v;
4244  short *ww=iv2array(w,R);
4245  poly u1=p_JetW(p_Sub(p_One(R),p_Mult_nn(u,u0,R),R),n,ww,R);
4246  if(u1==NULL)
4247  {
4248    omFreeSize((ADDRESS)ww,(rVar(R)+1)*sizeof(short));
4249    return v;
4250  }
4251  poly v1=p_Mult_nn(p_Copy(u1,R),u0,R);
4252  v=p_Add_q(v,p_Copy(v1,R),R);
4253  for(int i=n/p_MinDeg(u1,w,R);i>1;i--)
4254  {
4255    v1=p_JetW(p_Mult_q(v1,p_Copy(u1,R),R),n,ww,R);
4256    v=p_Add_q(v,p_Copy(v1,R),R);
4257  }
4258  p_Delete(&u1,R);
4259  p_Delete(&v1,R);
4260  omFreeSize((ADDRESS)ww,(rVar(R)+1)*sizeof(short));
4261  return v;
4262}
4263
4264BOOLEAN p_EqualPolys(poly p1,poly p2, const ring r)
4265{
4266  while ((p1 != NULL) && (p2 != NULL))
4267  {
4268    if (! p_LmEqual(p1, p2,r))
4269      return FALSE;
4270    if (! n_Equal(p_GetCoeff(p1,r), p_GetCoeff(p2,r),r->cf ))
4271      return FALSE;
4272    pIter(p1);
4273    pIter(p2);
4274  }
4275  return (p1==p2);
4276}
4277
4278static inline BOOLEAN p_ExpVectorEqual(poly p1, poly p2, const ring r1, const ring r2)
4279{
4280  assume( r1 == r2 || rSamePolyRep(r1, r2) );
4281
4282  p_LmCheckPolyRing1(p1, r1);
4283  p_LmCheckPolyRing1(p2, r2);
4284
4285  int i = r1->ExpL_Size;
4286
4287  assume( r1->ExpL_Size == r2->ExpL_Size );
4288
4289  unsigned long *ep = p1->exp;
4290  unsigned long *eq = p2->exp;
4291
4292  do
4293  {
4294    i--;
4295    if (ep[i] != eq[i]) return FALSE;
4296  }
4297  while (i);
4298
4299  return TRUE;
4300}
4301
4302BOOLEAN p_EqualPolys(poly p1,poly p2, const ring r1, const ring r2)
4303{
4304  assume( r1 == r2 || rSamePolyRep(r1, r2) ); // will be used in rEqual!
4305  assume( r1->cf == r2->cf );
4306
4307  while ((p1 != NULL) && (p2 != NULL))
4308  {
4309    // returns 1 if ExpVector(p)==ExpVector(q): does not compare numbers !!
4310    // #define p_LmEqual(p1, p2, r) p_ExpVectorEqual(p1, p2, r)
4311
4312    if (! p_ExpVectorEqual(p1, p2, r1, r2))
4313      return FALSE;
4314
4315    if (! n_Equal(p_GetCoeff(p1,r1), p_GetCoeff(p2,r2), r1->cf ))
4316      return FALSE;
4317
4318    pIter(p1);
4319    pIter(p2);
4320  }
4321  return (p1==p2);
4322}
4323
4324/*2
4325*returns TRUE if p1 is a skalar multiple of p2
4326*assume p1 != NULL and p2 != NULL
4327*/
4328BOOLEAN p_ComparePolys(poly p1,poly p2, const ring r)
4329{
4330  number n,nn;
4331  pAssume(p1 != NULL && p2 != NULL);
4332
4333  if (!p_LmEqual(p1,p2,r)) //compare leading mons
4334      return FALSE;
4335  if ((pNext(p1)==NULL) && (pNext(p2)!=NULL))
4336     return FALSE;
4337  if ((pNext(p2)==NULL) && (pNext(p1)!=NULL))
4338     return FALSE;
4339  if (pLength(p1) != pLength(p2))
4340    return FALSE;
4341#ifdef HAVE_RINGS
4342  if (rField_is_Ring(r))
4343  {
4344    if (!n_DivBy(p_GetCoeff(p1, r), p_GetCoeff(p2, r), r)) return FALSE;
4345  }
4346#endif
4347  n=n_Div(p_GetCoeff(p1,r),p_GetCoeff(p2,r),r);
4348  while ((p1 != NULL) /*&& (p2 != NULL)*/)
4349  {
4350    if ( ! p_LmEqual(p1, p2,r))
4351    {
4352        n_Delete(&n, r);
4353        return FALSE;
4354    }
4355    if (!n_Equal(p_GetCoeff(p1, r), nn = n_Mult(p_GetCoeff(p2, r),n, r->cf), r->cf))
4356    {
4357      n_Delete(&n, r);
4358      n_Delete(&nn, r);
4359      return FALSE;
4360    }
4361    n_Delete(&nn, r);
4362    pIter(p1);
4363    pIter(p2);
4364  }
4365  n_Delete(&n, r);
4366  return TRUE;
4367}
4368
4369/*2
4370* returns the length of a (numbers of monomials)
4371* respect syzComp
4372*/
4373poly p_Last(const poly p, int &l, const ring r)
4374{
4375  if (p == NULL)
4376  {
4377    l = 0;
4378    return NULL;
4379  }
4380  l = 1;
4381  poly a = p;
4382  if (! rIsSyzIndexRing(r))
4383  {
4384    poly next = pNext(a);
4385    while (next!=NULL)
4386    {
4387      a = next;
4388      next = pNext(a);
4389      l++;
4390    }
4391  }
4392  else
4393  {
4394    int curr_limit = rGetCurrSyzLimit(r);
4395    poly pp = a;
4396    while ((a=pNext(a))!=NULL)
4397    {
4398      if (p_GetComp(a,r)<=curr_limit/*syzComp*/)
4399        l++;
4400      else break;
4401      pp = a;
4402    }
4403    a=pp;
4404  }
4405  return a;
4406}
4407
4408int p_Var(poly m,const ring r)
4409{
4410  if (m==NULL) return 0;
4411  if (pNext(m)!=NULL) return 0;
4412  int i,e=0;
4413  for (i=rVar(r); i>0; i--)
4414  {
4415    int exp=p_GetExp(m,i,r);
4416    if (exp==1)
4417    {
4418      if (e==0) e=i;
4419      else return 0;
4420    }
4421    else if (exp!=0)
4422    {
4423      return 0;
4424    }
4425  }
4426  return e;
4427}
4428
4429/*2
4430*the minimal index of used variables - 1
4431*/
4432int p_LowVar (poly p, const ring r)
4433{
4434  int k,l,lex;
4435
4436  if (p == NULL) return -1;
4437
4438  k = 32000;/*a very large dummy value*/
4439  while (p != NULL)
4440  {
4441    l = 1;
4442    lex = p_GetExp(p,l,r);
4443    while ((l < (rVar(r))) && (lex == 0))
4444    {
4445      l++;
4446      lex = p_GetExp(p,l,r);
4447    }
4448    l--;
4449    if (l < k) k = l;
4450    pIter(p);
4451  }
4452  return k;
4453}
4454
4455/*2
4456* verschiebt die Indizees der Modulerzeugenden um i
4457*/
4458void p_Shift (poly * p,int i, const ring r)
4459{
4460  poly qp1 = *p,qp2 = *p;/*working pointers*/
4461  int     j = p_MaxComp(*p,r),k = p_MinComp(*p,r);
4462
4463  if (j+i < 0) return ;
4464  while (qp1 != NULL)
4465  {
4466    if ((p_GetComp(qp1,r)+i > 0) || ((j == -i) && (j == k)))
4467    {
4468      p_AddComp(qp1,i,r);
4469      p_SetmComp(qp1,r);
4470      qp2 = qp1;
4471      pIter(qp1);
4472    }
4473    else
4474    {
4475      if (qp2 == *p)
4476      {
4477        pIter(*p);
4478        p_LmDelete(&qp2,r);
4479        qp2 = *p;
4480        qp1 = *p;
4481      }
4482      else
4483      {
4484        qp2->next = qp1->next;
4485        if (qp1!=NULL) p_LmDelete(&qp1,r);
4486        qp1 = qp2->next;
4487      }
4488    }
4489  }
4490}
4491
4492/***************************************************************
4493 *
4494 * Storage Managament Routines
4495 *
4496 ***************************************************************/
4497
4498
4499static inline unsigned long GetBitFields(const long e,
4500                                         const unsigned int s, const unsigned int n)
4501{
4502#define Sy_bit_L(x)     (((unsigned long)1L)<<(x))
4503  unsigned int i = 0;
4504  unsigned long  ev = 0L;
4505  assume(n > 0 && s < BIT_SIZEOF_LONG);
4506  do
4507  {
4508    assume(s+i < BIT_SIZEOF_LONG);
4509    if (e > (long) i) ev |= Sy_bit_L(s+i);
4510    else break;
4511    i++;
4512  }
4513  while (i < n);
4514  return ev;
4515}
4516
4517// Short Exponent Vectors are used for fast divisibility tests
4518// ShortExpVectors "squeeze" an exponent vector into one word as follows:
4519// Let n = BIT_SIZEOF_LONG / pVariables.
4520// If n == 0 (i.e. pVariables > BIT_SIZE_OF_LONG), let m == the number
4521// of non-zero exponents. If (m>BIT_SIZEOF_LONG), then sev = ~0, else
4522// first m bits of sev are set to 1.
4523// Otherwise (i.e. pVariables <= BIT_SIZE_OF_LONG)
4524// represented by a bit-field of length n (resp. n+1 for some
4525// exponents). If the value of an exponent is greater or equal to n, then
4526// all of its respective n bits are set to 1. If the value of an exponent
4527// is smaller than n, say m, then only the first m bits of the respective
4528// n bits are set to 1, the others are set to 0.
4529// This way, we have:
4530// exp1 / exp2 ==> (ev1 & ~ev2) == 0, i.e.,
4531// if (ev1 & ~ev2) then exp1 does not divide exp2
4532unsigned long p_GetShortExpVector(const poly p, const ring r)
4533{
4534  assume(p != NULL);
4535  unsigned long ev = 0; // short exponent vector
4536  unsigned int n = BIT_SIZEOF_LONG / r->N; // number of bits per exp
4537  unsigned int m1; // highest bit which is filled with (n+1)
4538  int i=0,j=1;
4539
4540  if (n == 0)
4541  {
4542    if (r->N <2*BIT_SIZEOF_LONG)
4543    {
4544      n=1;
4545      m1=0;
4546    }
4547    else
4548    {
4549      for (; j<=r->N; j++)
4550      {
4551        if (p_GetExp(p,j,r) > 0) i++;
4552        if (i == BIT_SIZEOF_LONG) break;
4553      }
4554      if (i>0)
4555        ev = ~(0UL) >> (BIT_SIZEOF_LONG - i);
4556      return ev;
4557    }
4558  }
4559  else
4560  {
4561    m1 = (n+1)*(BIT_SIZEOF_LONG - n*r->N);
4562  }
4563
4564  n++;
4565  while (i<m1)
4566  {
4567    ev |= GetBitFields(p_GetExp(p, j,r), i, n);
4568    i += n;
4569    j++;
4570  }
4571
4572  n--;
4573  while (i<BIT_SIZEOF_LONG)
4574  {
4575    ev |= GetBitFields(p_GetExp(p, j,r), i, n);
4576    i += n;
4577    j++;
4578  }
4579  return ev;
4580}
4581
4582
4583///  p_GetShortExpVector of p * pp
4584unsigned long p_GetShortExpVector(const poly p, const poly pp, const ring r)
4585{
4586  assume(p != NULL);
4587  assume(pp != NULL);
4588
4589  unsigned long ev = 0; // short exponent vector
4590  unsigned int n = BIT_SIZEOF_LONG / r->N; // number of bits per exp
4591  unsigned int m1; // highest bit which is filled with (n+1)
4592  int j=1;
4593  unsigned long i = 0L;
4594
4595  if (n == 0)
4596  {
4597    if (r->N <2*BIT_SIZEOF_LONG)
4598    {
4599      n=1;
4600      m1=0;
4601    }
4602    else
4603    {
4604      for (; j<=r->N; j++)
4605      {
4606        if (p_GetExp(p,j,r) > 0 || p_GetExp(pp,j,r) > 0) i++;
4607        if (i == BIT_SIZEOF_LONG) break;
4608      }
4609      if (i>0)
4610        ev = ~(0UL) >> (BIT_SIZEOF_LONG - i);
4611      return ev;
4612    }
4613  }
4614  else
4615  {
4616    m1 = (n+1)*(BIT_SIZEOF_LONG - n*r->N);
4617  }
4618
4619  n++;
4620  while (i<m1)
4621  {
4622    ev |= GetBitFields(p_GetExp(p, j,r) + p_GetExp(pp, j,r), i, n);
4623    i += n;
4624    j++;
4625  }
4626
4627  n--;
4628  while (i<BIT_SIZEOF_LONG)
4629  {
4630    ev |= GetBitFields(p_GetExp(p, j,r) + p_GetExp(pp, j,r), i, n);
4631    i += n;
4632    j++;
4633  }
4634  return ev;
4635}
4636
4637
4638
4639/***************************************************************
4640 *
4641 * p_ShallowDelete
4642 *
4643 ***************************************************************/
4644#undef LINKAGE
4645#define LINKAGE
4646#undef p_Delete__T
4647#define p_Delete__T p_ShallowDelete
4648#undef n_Delete__T
4649#define n_Delete__T(n, r) do {} while (0)
4650
4651#include <polys/templates/p_Delete__T.cc>
4652
Note: See TracBrowser for help on using the repository browser.