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

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