source: git/libpolys/polys/monomials/p_polys.cc @ 887ce9e

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