source: git/libpolys/polys/monomials/p_polys.h @ 18dab28

spielwiese
Last change on this file since 18dab28 was 18dab28, checked in by Hans Schoenemann <hannes@…>, 13 years ago
fix unseless includes of polys-impl.h
  • Property mode set to 100644
File size: 50.5 KB
Line 
1/****************************************
2*  Computer Algebra System SINGULAR     *
3****************************************/
4/***************************************************************
5 *  File:    p_polys.h
6 *  Purpose: declaration of poly stuf which are independent of
7 *           currRing
8 *  Author:  obachman (Olaf Bachmann)
9 *  Created: 9/00
10 *  Version: $Id$
11 *******************************************************************/
12/***************************************************************
13 *  Purpose: implementation of poly procs which iter over ExpVector
14 *  Author:  obachman (Olaf Bachmann)
15 *  Created: 8/00
16 *  Version: $Id$
17 *******************************************************************/
18#ifndef P_POLYS_H
19#define P_POLYS_H
20
21#include <omalloc/omalloc.h>
22#include <misc/mylimits.h>
23#include <coeffs/coeffs.h>
24
25#include <polys/monomials/ring.h>
26#include <polys/monomials/monomials.h>
27
28#include <polys/templates/p_MemAdd.h>
29#include <polys/templates/p_Procs.h>
30
31#include <polys/sbuckets.h>
32
33#ifdef HAVE_PLURAL
34#include <polys/nc/nc.h>
35#endif
36
37
38/***************************************************************
39 *
40 * Primitives for accessing and setting fields of a poly
41 * poly must be != NULL
42 *
43 ***************************************************************/
44// next
45#define pNext(p)            ((p)->next)
46#define pIter(p)            ((p) = (p)->next)
47
48// coeff
49// #define pGetCoeff(p)        ((p)->coef)
50static inline number& pGetCoeff(poly p)
51{
52  assume(p != NULL);
53  return p->coef;
54}
55
56// #define p_GetCoeff(p,r)     pGetCoeff(p)
57static inline number& p_GetCoeff(poly p, const ring r)
58{
59  assume(p != NULL);
60  assume(r != NULL);
61  return p->coef;
62}
63
64
65
66//
67// deletes old coeff before setting the new one???
68#define pSetCoeff0(p,n)     (p)->coef=(n)
69
70#define p_SetCoeff0(p,n,r)  pSetCoeff0(p,n)
71
72#define __p_GetComp(p, r)   (p)->exp[r->pCompIndex]
73#define p_GetComp(p, r)    ((long) (r->pCompIndex >= 0 ? __p_GetComp(p, r) : 0))
74
75/***************************************************************
76 *
77 * Divisiblity tests, args must be != NULL, except for
78 * pDivisbleBy
79 *
80 ***************************************************************/
81unsigned long p_GetShortExpVector(poly a, const ring r);
82
83/* divisibility check over ground ring (which may contain zero divisors);
84   TRUE iff LT(f) divides LT(g), i.e., LT(f)*c*m = LT(g), for some
85   coefficient c and some monomial m;
86   does not take components into account */
87#ifdef HAVE_RINGS
88BOOLEAN p_DivisibleByRingCase(poly f, poly g, const ring r);
89#endif
90
91/***************************************************************
92 *
93 * Misc things on polys
94 *
95 ***************************************************************/
96
97poly p_One(const ring r);
98
99int p_MinDeg(poly p,intvec *w, const ring R);
100
101long p_DegW(poly p, const short *w, const ring R);
102
103// return TRUE if all monoms have the same component
104BOOLEAN   p_OneComp(poly p, const ring r);
105
106// return i, if head depends only on var(i)
107int       p_IsPurePower(const poly p, const ring r);
108
109// return i, if poly depends only on var(i)
110int       p_IsUnivariate(poly p, const ring r);
111
112// set entry e[i] to 1 if var(i) occurs in p, ignore var(j) if e[j]>0
113// return #(e[i]>0)
114int      p_GetVariables(poly p, int * e, const ring r);
115
116// returns the poly representing the integer i
117poly      p_ISet(int i, const ring r);
118
119// returns the poly representing the number n, destroys n
120poly      p_NSet(number n, const ring r);
121
122void  p_Vec2Polys(poly v, poly**p, int *len, const ring r);
123
124/***************************************************************
125 *
126 * Copying/Deletion of polys: args may be NULL
127 *
128 ***************************************************************/
129
130// simply deletes monomials, does not free coeffs
131void p_ShallowDelete(poly *p, const ring r);
132
133
134
135/***************************************************************
136 *
137 * Copying/Deleteion of polys: args may be NULL
138 *  - p/q as arg mean a poly
139 *  - m a monomial
140 *  - n a number
141 *  - pp (resp. qq, mm, nn) means arg is constant
142 *  - p (resp, q, m, n)     means arg is destroyed
143 *
144 ***************************************************************/
145
146poly      p_Sub(poly a, poly b, const ring r);
147
148poly      p_Power(poly p, int i, const ring r);
149
150
151/***************************************************************
152 *
153 * PDEBUG stuff
154 *
155 ***************************************************************/
156#ifdef PDEBUG
157// Returns TRUE if m is monom of p, FALSE otherwise
158BOOLEAN pIsMonomOf(poly p, poly m);
159// Returns TRUE if p and q have common monoms
160BOOLEAN pHaveCommonMonoms(poly p, poly q);
161
162// p_Check* routines return TRUE if everything is ok,
163// else, they report error message and return false
164
165// check if Lm(p) is from ring r
166BOOLEAN p_LmCheckIsFromRing(poly p, ring r);
167// check if Lm(p) != NULL, r != NULL and initialized && Lm(p) is from r
168BOOLEAN p_LmCheckPolyRing(poly p, ring r);
169// check if all monoms of p are from ring r
170BOOLEAN p_CheckIsFromRing(poly p, ring r);
171// check r != NULL and initialized && all monoms of p are from r
172BOOLEAN p_CheckPolyRing(poly p, ring r);
173// check if r != NULL and initialized
174BOOLEAN p_CheckRing(ring r);
175// only do check if cond
176
177
178#define pIfThen(cond, check) do {if (cond) {check;}} while (0)
179
180BOOLEAN _p_Test(poly p, ring r, int level);
181BOOLEAN _p_LmTest(poly p, ring r, int level);
182BOOLEAN _pp_Test(poly p, ring lmRing, ring tailRing, int level);
183
184#define p_Test(p,r)     _p_Test(p, r, PDEBUG)
185#define p_LmTest(p,r)   _p_LmTest(p, r, PDEBUG)
186#define pp_Test(p, lmRing, tailRing)    _pp_Test(p, lmRing, tailRing, PDEBUG)
187
188#else // ! PDEBUG
189
190#define pIsMonomOf(p, q)        (TRUE)
191#define pHaveCommonMonoms(p, q) (TRUE)
192#define p_LmCheckIsFromRing(p,r)  ((void)0)
193#define p_LmCheckPolyRing(p,r)    ((void)0)
194#define p_CheckIsFromRing(p,r)  ((void)0)
195#define p_CheckPolyRing(p,r)    ((void)0)
196#define p_CheckRing(r)          ((void)0)
197#define P_CheckIf(cond, check)  ((void)0)
198
199#define p_Test(p,r)     (1)
200#define p_LmTest(p,r)   (1)
201#define pp_Test(p, lmRing, tailRing) (1)
202
203#endif
204
205/***************************************************************
206 *
207 * Misc stuff
208 *
209 ***************************************************************/
210/*2
211* returns the length of a polynomial (numbers of monomials)
212*/
213static inline int pLength(poly a)
214{
215  int l = 0;
216  while (a!=NULL)
217  {
218    pIter(a);
219    l++;
220  }
221  return l;
222}
223
224void      p_Norm(poly p1, const ring r);
225void      p_Normalize(poly p,const ring r);
226
227void      p_Content(poly p, const ring r);
228//void      p_SimpleContent(poly p, int s, const ring r);
229
230poly      p_Cleardenom(poly p, const ring r);
231void      p_Cleardenom_n(poly p, const ring r,number &c);
232number    p_GetAllDenom(poly ph, const ring r);
233
234int       p_Size( poly p, const ring r );
235
236// homogenizes p by multiplying certain powers of the varnum-th variable
237poly      p_Homogen (poly p, int varnum, const ring r);
238
239BOOLEAN   p_IsHomogeneous (poly p, const ring r);
240
241static inline void p_Setm(poly p, const ring r);
242p_SetmProc p_GetSetmProc(ring r);
243
244poly      p_Subst(poly p, int n, poly e, const ring r);
245
246// TODO:
247#define p_SetmComp  p_Setm
248
249// component
250static inline  unsigned long p_SetComp(poly p, unsigned long c, ring r)
251{
252  p_LmCheckPolyRing2(p, r);
253  pAssume2(rRing_has_Comp(r));
254  __p_GetComp(p,r) = c;
255  return c;
256}
257// sets component of poly a to i, returns length of p
258static inline   void p_SetCompP(poly p, int i, ring r)
259{
260  if (p != NULL)
261  {
262#ifdef PDEBUG
263    poly q = p;
264    int l = 0;
265#endif
266
267    if (rOrd_SetCompRequiresSetm(r))
268    {
269      do
270      {
271        p_SetComp(p, i, r);
272        p_SetmComp(p, r);
273#ifdef PDEBUG
274        l++;
275#endif
276        pIter(p);
277      }
278      while (p != NULL);
279    }
280    else
281    {
282      do
283      {
284        p_SetComp(p, i, r);
285#ifdef PDEBUG
286        l++;
287#endif
288        pIter(p);
289      }
290      while(p != NULL);
291    }
292#ifdef PDEBUG
293    p_Test(q, r);
294    assume(l == pLength(q));
295#endif
296  }
297}
298
299static inline   void p_SetCompP(poly p, int i, ring lmRing, ring tailRing)
300{
301  if (p != NULL)
302  {
303    p_SetComp(p, i, lmRing);
304    p_SetmComp(p, lmRing);
305    p_SetCompP(pNext(p), i, tailRing);
306  }
307}
308
309// returns maximal column number in the modul element a (or 0)
310static inline long p_MaxComp(poly p, ring lmRing, ring tailRing)
311{
312  long result,i;
313
314  if(p==NULL) return 0;
315  result = p_GetComp(p, lmRing);
316  if (result != 0)
317  {
318    loop
319    {
320      pIter(p);
321      if(p==NULL) break;
322      i = p_GetComp(p, tailRing);
323      if (i>result) result = i;
324    }
325  }
326  return result;
327}
328
329static inline long p_MaxComp(poly p,ring lmRing) {return p_MaxComp(p,lmRing,lmRing);}
330
331static inline   long p_MinComp(poly p, ring lmRing, ring tailRing)
332{
333  long result,i;
334
335  if(p==NULL) return 0;
336  result = p_GetComp(p,lmRing);
337  if (result != 0)
338  {
339    loop
340    {
341      pIter(p);
342      if(p==NULL) break;
343      i = p_GetComp(p,tailRing);
344      if (i<result) result = i;
345    }
346  }
347  return result;
348}
349
350static inline long p_MinComp(poly p,ring lmRing) {return p_MinComp(p,lmRing,lmRing);}
351
352/***************************************************************
353 *
354 * poly things which are independent of ring
355 *
356 ***************************************************************/
357
358// returns the length of a polynomial (numbers of monomials)
359// respect syzComp
360// static inline poly pLast(poly a, int &length);
361// static inline poly pLast(poly a) { int l; return pLast(a, l); }
362
363
364static inline poly pReverse(poly p)
365{
366  if (p == NULL || pNext(p) == NULL) return p;
367
368  poly q = pNext(p), // == pNext(p)
369    qn;
370  pNext(p) = NULL;
371  do
372  {
373    qn = pNext(q);
374    pNext(q) = p;
375    p = q;
376    q = qn;
377  }
378  while (qn != NULL);
379  return p;
380}
381void      pEnlargeSet(poly**p, int length, int increment);
382
383
384/***************************************************************
385 *
386 * I/O
387 *
388 ***************************************************************/
389char*     p_String(poly p, ring lmRing, ring tailRing);
390char*     p_String0(poly p, ring lmRing, ring tailRing);
391void      p_Write(poly p, ring lmRing, ring tailRing);
392void      p_Write0(poly p, ring lmRing, ring tailRing);
393void      p_wrp(poly p, ring lmRing, ring tailRing);
394
395/***************************************************************
396 *
397 * Degree stuff -- see p_polys.cc for explainations
398 *
399 ***************************************************************/
400extern pLDegProc pLDeg;
401
402static inline long  p_FDeg(const poly p, const ring r)  { return r->pFDeg(p,r); }
403static inline long  p_LDeg(const poly p, int *l, const ring r)  { return r->pLDeg(p,l,r); }
404
405long p_WFirstTotalDegree(poly p, ring r);
406long p_WTotaldegree(poly p, const ring r);
407long p_WDegree(poly p,const ring r);
408long pLDeg0(poly p,int *l, ring r);
409long pLDeg0c(poly p,int *l, ring r);
410long pLDegb(poly p,int *l, ring r);
411long pLDeg1(poly p,int *l, ring r);
412long pLDeg1c(poly p,int *l, ring r);
413long pLDeg1_Deg(poly p,int *l, ring r);
414long pLDeg1c_Deg(poly p,int *l, ring r);
415long pLDeg1_Totaldegree(poly p,int *l, ring r);
416long pLDeg1c_Totaldegree(poly p,int *l, ring r);
417long pLDeg1_WFirstTotalDegree(poly p,int *l, ring r);
418long pLDeg1c_WFirstTotalDegree(poly p,int *l, ring r);
419BOOLEAN p_EqualPolys(poly p1, poly p2, const ring r);
420
421long p_Deg(poly a, const ring r);
422
423
424/***************************************************************
425 *
426 * Primitives for accessing and setting fields of a poly
427 *
428 ***************************************************************/
429
430static inline number p_SetCoeff(poly p, number n, ring r)
431{
432  p_LmCheckPolyRing2(p, r);
433  n_Delete(&(p->coef), r->cf);
434  (p)->coef=n;
435  return n;
436}
437
438// order
439static inline long p_GetOrder(poly p, ring r)
440{
441  p_LmCheckPolyRing2(p, r);
442  if (r->typ==NULL) return ((p)->exp[r->pOrdIndex]);
443  int i=0;
444  loop
445  {
446    switch(r->typ[i].ord_typ)
447    {
448      case ro_wp_neg:
449        return (((long)((p)->exp[r->pOrdIndex]))-POLY_NEGWEIGHT_OFFSET);
450      case ro_syzcomp:
451      case ro_syz:
452      case ro_cp:
453        i++;
454        break;
455      //case ro_dp:
456      //case ro_wp:
457      default:
458        return ((p)->exp[r->pOrdIndex]);
459    }
460  }
461}
462
463// Setm
464static inline void p_Setm(poly p, const ring r)
465{
466  p_CheckRing2(r);
467  r->p_Setm(p, r);
468}
469
470
471static inline unsigned long p_AddComp(poly p, unsigned long v, ring r)
472{
473  p_LmCheckPolyRing2(p, r);
474  pAssume2(rRing_has_Comp(r));
475  return __p_GetComp(p,r) += v;
476}
477static inline unsigned long p_SubComp(poly p, unsigned long v, ring r)
478{
479  p_LmCheckPolyRing2(p, r);
480  pAssume2(rRing_has_Comp(r));
481  _pPolyAssume2(__p_GetComp(p,r) >= v,p,r);
482  return __p_GetComp(p,r) -= v;
483}
484
485#ifndef HAVE_EXPSIZES
486
487/// get a single variable exponent
488/// @Note:
489/// the integer VarOffset encodes:
490/// 1. the position of a variable in the exponent vector p->exp (lower 24 bits)
491/// 2. number of bits to shift to the right in the upper 8 bits (which takes at most 6 bits for 64 bit)
492/// Thus VarOffset always has 2 zero higher bits!
493static inline long p_GetExp(const poly p, const unsigned long iBitmask, const int VarOffset)
494{
495  pAssume2((VarOffset >> (24 + 6)) == 0);
496#if 0
497  int pos=(VarOffset & 0xffffff);
498  int bitpos=(VarOffset >> 24);
499  unsigned long exp=(p->exp[pos] >> bitmask) & iBitmask;
500  return exp;
501#else
502  return (long)
503         ((p->exp[(VarOffset & 0xffffff)] >> (VarOffset >> 24))
504          & iBitmask);
505#endif
506}
507
508
509/// set a single variable exponent
510/// @Note:
511/// VarOffset encodes the position in p->exp @see p_GetExp
512static inline unsigned long p_SetExp(poly p, const unsigned long e, const unsigned long iBitmask, const int VarOffset)
513{
514  pAssume2(e>=0);
515  pAssume2(e<=iBitmask);
516  pAssume2((VarOffset >> (24 + 6)) == 0);
517
518  // shift e to the left:
519  register int shift = VarOffset >> 24;
520  unsigned long ee = e << shift /*(VarOffset >> 24)*/;
521  // find the bits in the exponent vector
522  register int offset = (VarOffset & 0xffffff);
523  // clear the bits in the exponent vector:
524  p->exp[offset]  &= ~( iBitmask << shift );
525  // insert e with |
526  p->exp[ offset ] |= ee;
527  return e;
528}
529
530
531#else // #ifdef HAVE_EXPSIZES // EXPERIMENTAL!!!
532
533static inline unsigned long BitMask(unsigned long bitmask, int twobits)
534{
535  // bitmask = 00000111111111111
536  // 0 must give bitmask!
537  // 1, 2, 3 - anything like 00011..11
538  pAssume2((twobits >> 2) == 0);
539  static const unsigned long _bitmasks[4] = {-1, 0x7fff, 0x7f, 0x3};
540  return bitmask & _bitmasks[twobits];
541}
542
543
544/// @Note: we may add some more info (6 ) into VarOffset and thus encode
545static inline long p_GetExp(const poly p, const unsigned long iBitmask, const int VarOffset)
546{
547  int pos  =(VarOffset & 0xffffff);
548  int hbyte= (VarOffset >> 24); // the highest byte
549  int bitpos = hbyte & 0x3f; // last 6 bits
550  long bitmask = BitMask(iBitmask, hbyte >> 6);
551
552  long exp=(p->exp[pos] >> bitpos) & bitmask;
553  return exp;
554
555}
556
557static inline long p_SetExp(poly p, const long e, const unsigned long iBitmask, const int VarOffset)
558{
559  pAssume2(e>=0);
560  pAssume2(e <= BitMask(iBitmask, VarOffset >> 30));
561
562  // shift e to the left:
563  register int hbyte = VarOffset >> 24;
564  int bitmask = BitMask(iBitmask, hbyte >> 6);
565  register int shift = hbyte & 0x3f;
566  long ee = e << shift;
567  // find the bits in the exponent vector
568  register int offset = (VarOffset & 0xffffff);
569  // clear the bits in the exponent vector:
570  p->exp[offset]  &= ~( bitmask << shift );
571  // insert e with |
572  p->exp[ offset ] |= ee;
573  return e;
574}
575
576#endif // #ifndef HAVE_EXPSIZES
577
578
579static inline long p_GetExp(const poly p, const ring r, const int VarOffset)
580{
581  p_LmCheckPolyRing2(p, r);
582  pAssume2(VarOffset != -1);
583  return p_GetExp(p, r->bitmask, VarOffset);
584}
585
586static inline long p_SetExp(poly p, const long e, const ring r, const int VarOffset)
587{
588  p_LmCheckPolyRing2(p, r);
589  pAssume2(VarOffset != -1);
590  return p_SetExp(p, e, r->bitmask, VarOffset);
591}
592
593
594
595/// get v^th exponent for a monomial
596static inline long p_GetExp(const poly p, const int v, const ring r)
597{
598  p_LmCheckPolyRing2(p, r);
599  pAssume2(v>0 && v <= r->N);
600  pAssume2(r->VarOffset[v] != -1);
601  return p_GetExp(p, r->bitmask, r->VarOffset[v]);
602}
603
604
605/// set v^th exponent for a monomial
606static inline long p_SetExp(poly p, const int v, const long e, const ring r)
607{
608  p_LmCheckPolyRing2(p, r);
609  pAssume2(v>0 && v <= r->N);
610  pAssume2(r->VarOffset[v] != -1);
611  return p_SetExp(p, e, r->bitmask, r->VarOffset[v]);
612}
613
614// the following should be implemented more efficiently
615static inline  long p_IncrExp(poly p, int v, ring r)
616{
617  p_LmCheckPolyRing2(p, r);
618  int e = p_GetExp(p,v,r);
619  e++;
620  return p_SetExp(p,v,e,r);
621}
622static inline  long p_DecrExp(poly p, int v, ring r)
623{
624  p_LmCheckPolyRing2(p, r);
625  int e = p_GetExp(p,v,r);
626  pAssume2(e > 0);
627  e--;
628  return p_SetExp(p,v,e,r);
629}
630static inline  long p_AddExp(poly p, int v, long ee, ring r)
631{
632  p_LmCheckPolyRing2(p, r);
633  int e = p_GetExp(p,v,r);
634  e += ee;
635  return p_SetExp(p,v,e,r);
636}
637static inline  long p_SubExp(poly p, int v, long ee, ring r)
638{
639  p_LmCheckPolyRing2(p, r);
640  long e = p_GetExp(p,v,r);
641  pAssume2(e >= ee);
642  e -= ee;
643  return p_SetExp(p,v,e,r);
644}
645static inline  long p_MultExp(poly p, int v, long ee, ring r)
646{
647  p_LmCheckPolyRing2(p, r);
648  long e = p_GetExp(p,v,r);
649  e *= ee;
650  return p_SetExp(p,v,e,r);
651}
652
653static inline long p_GetExpSum(poly p1, poly p2, int i, ring r)
654{
655  p_LmCheckPolyRing2(p1, r);
656  p_LmCheckPolyRing2(p2, r);
657  return p_GetExp(p1,i,r) + p_GetExp(p2,i,r);
658}
659static inline long p_GetExpDiff(poly p1, poly p2, int i, ring r)
660{
661  return p_GetExp(p1,i,r) - p_GetExp(p2,i,r);
662}
663
664static inline int p_Comp_k_n(poly a, poly b, int k, ring r)
665{
666  if ((a==NULL) || (b==NULL) ) return FALSE;
667  p_LmCheckPolyRing2(a, r);
668  p_LmCheckPolyRing2(b, r);
669  pAssume2(k > 0 && k <= r->N);
670  int i=k;
671  for(;i<=r->N;i++)
672  {
673    if (p_GetExp(a,i,r) != p_GetExp(b,i,r)) return FALSE;
674    //    if (a->exp[(r->VarOffset[i] & 0xffffff)] != b->exp[(r->VarOffset[i] & 0xffffff)]) return FALSE;
675  }
676  return TRUE;
677}
678
679
680/***************************************************************
681 *
682 * Allocation/Initalization/Deletion
683 *
684 ***************************************************************/
685#if PDEBUG > 2
686static inline poly p_New(const ring r, omBin bin)
687#else
688static inline poly p_New(const ring, omBin bin)
689#endif
690{
691  p_CheckRing2(r);
692  pAssume2(bin != NULL && r->PolyBin->sizeW == bin->sizeW);
693  poly p;
694  omTypeAllocBin(poly, p, bin);
695  p_SetRingOfLm(p, r);
696  return p;
697}
698
699static inline poly p_New(ring r)
700{
701  return p_New(r, r->PolyBin);
702}
703
704#if PDEBUG > 2
705static inline void p_LmFree(poly p, ring r)
706#else
707static inline void p_LmFree(poly p, ring)
708#endif
709{
710  p_LmCheckPolyRing2(p, r);
711  omFreeBinAddr(p);
712}
713#if PDEBUG > 2
714static inline void p_LmFree(poly *p, ring r)
715#else
716static inline void p_LmFree(poly *p, ring) 
717#endif
718{
719  p_LmCheckPolyRing2(*p, r);
720  poly h = *p;
721  *p = pNext(h);
722  omFreeBinAddr(h);
723}
724#if PDEBUG > 2
725static inline poly p_LmFreeAndNext(poly p, ring r)
726#else
727static inline poly p_LmFreeAndNext(poly p, ring)
728#endif
729{
730  p_LmCheckPolyRing2(p, r);
731  poly pnext = pNext(p);
732  omFreeBinAddr(p);
733  return pnext;
734}
735static inline void p_LmDelete(poly p, const ring r)
736{
737  p_LmCheckPolyRing2(p, r);
738  n_Delete(&pGetCoeff(p), r->cf);
739  omFreeBinAddr(p);
740}
741static inline void p_LmDelete(poly *p, const ring r)
742{
743  p_LmCheckPolyRing2(*p, r);
744  poly h = *p;
745  *p = pNext(h);
746  n_Delete(&pGetCoeff(h), r->cf);
747  omFreeBinAddr(h);
748}
749static inline poly p_LmDeleteAndNext(poly p, const ring r)
750{
751  p_LmCheckPolyRing2(p, r);
752  poly pnext = pNext(p);
753  n_Delete(&pGetCoeff(p), r->cf);
754  omFreeBinAddr(p);
755  return pnext;
756}
757
758/***************************************************************
759 *
760 * Misc routines
761 *
762 ***************************************************************/
763
764/// return the maximal exponent of p in form of the maximal long var
765unsigned long p_GetMaxExpL(poly p, const ring r, unsigned long l_max = 0);
766
767/// return monomial r such that GetExp(r,i) is maximum of all
768/// monomials in p; coeff == 0, next == NULL, ord is not set
769poly p_GetMaxExpP(poly p, ring r);
770
771static inline unsigned long p_GetMaxExp(const unsigned long l, const ring r)
772{
773  unsigned long bitmask = r->bitmask;
774  unsigned long max = (l & bitmask);
775  unsigned long j = r->ExpPerLong - 1;
776
777  if (j > 0)
778  {
779    unsigned long i = r->BitsPerExp;
780    long e;
781    loop
782    {
783      e = ((l >> i) & bitmask);
784      if ((unsigned long) e > max)
785        max = e;
786      j--;
787      if (j==0) break;
788      i += r->BitsPerExp;
789    }
790  }
791  return max;
792}
793
794static inline unsigned long p_GetMaxExp(const poly p, const ring r)
795{
796  return p_GetMaxExp(p_GetMaxExpL(p, r), r);
797}
798
799static inline unsigned long
800p_GetTotalDegree(const unsigned long l, const ring r, const int number_of_exps)
801{
802  const unsigned long bitmask = r->bitmask;
803  unsigned long sum = (l & bitmask);
804  unsigned long j = number_of_exps - 1;
805
806  if (j > 0)
807  {
808    unsigned long i = r->BitsPerExp;
809    loop
810    {
811      sum += ((l >> i) & bitmask);
812      j--;
813      if (j==0) break;
814      i += r->BitsPerExp;
815    }
816  }
817  return sum;
818}
819
820static inline unsigned long
821p_GetTotalDegree(const unsigned long l, const ring r)
822{
823  return p_GetTotalDegree(l, r, r->ExpPerLong);
824}
825
826/***************************************************************
827 *
828 * Dispatcher to r->p_Procs, they do the tests/checks
829 *
830 ***************************************************************/
831// returns a copy of p
832static inline poly p_Copy(poly p, const ring r)
833{
834#ifdef PDEBUG
835  poly pp= r->p_Procs->p_Copy(p, r);
836  p_Test(pp,r);
837  return pp;
838#else
839  return r->p_Procs->p_Copy(p, r);
840#endif
841}
842
843static inline poly p_Head(poly p, const ring r)
844{
845  if (p == NULL) return NULL;
846  p_LmCheckPolyRing1(p, r);
847  poly np;
848  omTypeAllocBin(poly, np, r->PolyBin);
849  p_SetRingOfLm(np, r);
850  memcpy(np->exp, p->exp, r->ExpL_Size*sizeof(long));
851  pNext(np) = NULL;
852  pSetCoeff0(np, n_Copy(pGetCoeff(p), r->cf));
853  return np;
854}
855
856// returns a copy of p with Lm(p) from lmRing and Tail(p) from tailRing
857static inline poly p_Copy(poly p, const ring lmRing, const ring tailRing)
858{
859#ifndef PDEBUG
860  if (tailRing == lmRing)
861    return tailRing->p_Procs->p_Copy(p, tailRing);
862#endif
863  if (p != NULL)
864  {
865    poly pres = p_Head(p, lmRing);
866    pNext(pres) = tailRing->p_Procs->p_Copy(pNext(p), tailRing);
867    return pres;
868  }
869  else
870    return NULL;
871}
872
873// deletes *p, and sets *p to NULL
874static inline void p_Delete(poly *p, const ring r)
875{
876  r->p_Procs->p_Delete(p, r);
877}
878
879static inline void p_Delete(poly *p,  const ring lmRing, const ring tailRing)
880{
881#ifndef PDEBUG
882  if (tailRing == lmRing)
883  {
884    tailRing->p_Procs->p_Delete(p, tailRing);
885    return;
886  }
887#endif
888  if (*p != NULL)
889  {
890    if (pNext(*p) != NULL)
891      tailRing->p_Procs->p_Delete(&pNext(*p), tailRing);
892    p_LmDelete(p, lmRing);
893  }
894}
895
896// copys monomials of p, allocates new monomials from bin,
897// deletes monomoals of p
898static inline poly p_ShallowCopyDelete(poly p, const ring r, omBin bin)
899{
900  p_LmCheckPolyRing2(p, r);
901  pAssume2(r->PolyBin->sizeW == bin->sizeW);
902  return r->p_Procs->p_ShallowCopyDelete(p, r, bin);
903}
904
905// returns p+q, destroys p and q
906static inline poly p_Add_q(poly p, poly q, const ring r)
907{
908  int shorter;
909  return r->p_Procs->p_Add_q(p, q, shorter, r);
910}
911
912/// like p_Add_q, except that if lp == pLength(lp) lq == pLength(lq) then lp == pLength(p+q)
913static inline poly p_Add_q(poly p, poly q, int &lp, int lq, const ring r)
914{
915  int shorter;
916  poly res = r->p_Procs->p_Add_q(p, q, shorter, r);
917  lp = (lp + lq) - shorter;
918  return res;
919}
920
921// returns p*n, destroys p
922static inline poly p_Mult_nn(poly p, number n, const ring r)
923{
924  if (n_IsOne(n, r->cf))
925    return p;
926  else
927    return r->p_Procs->p_Mult_nn(p, n, r);
928}
929
930static inline poly p_Mult_nn(poly p, number n, const ring lmRing,
931                        const ring tailRing)
932{
933#ifndef PDEBUG
934  if (lmRing == tailRing)
935  {
936    return p_Mult_nn(p, n, tailRing);
937  }
938#endif
939  poly pnext = pNext(p);
940  pNext(p) = NULL;
941  p = lmRing->p_Procs->p_Mult_nn(p, n, lmRing);
942  pNext(p) = tailRing->p_Procs->p_Mult_nn(pnext, n, tailRing);
943  return p;
944}
945
946// returns p*n, does not destroy p
947static inline poly pp_Mult_nn(poly p, number n, const ring r)
948{
949  if (n_IsOne(n, r->cf))
950    return p_Copy(p, r);
951  else
952    return r->p_Procs->pp_Mult_nn(p, n, r);
953}
954
955// test if the monomial is a constant as a vector component
956// i.e., test if all exponents are zero
957static inline BOOLEAN p_LmIsConstantComp(const poly p, const ring r)
958{
959  //p_LmCheckPolyRing(p, r);
960  int i = r->VarL_Size - 1;
961
962  do
963  {
964    if (p->exp[r->VarL_Offset[i]] != 0)
965      return FALSE;
966    i--;
967  }
968  while (i >= 0);
969  return TRUE;
970}
971
972// test if monomial is a constant, i.e. if all exponents and the component
973// is zero
974static inline BOOLEAN p_LmIsConstant(const poly p, const ring r)
975{
976  if (p_LmIsConstantComp(p, r))
977    return (p_GetComp(p, r) == 0);
978  return FALSE;
979}
980
981// returns Copy(p)*m, does neither destroy p nor m
982static inline poly pp_Mult_mm(poly p, poly m, const ring r)
983{
984  if (p_LmIsConstant(m, r))
985    return pp_Mult_nn(p, pGetCoeff(m), r);
986  else
987  {
988    poly last;
989    return r->p_Procs->pp_Mult_mm(p, m, r, last);
990  }
991}
992
993// returns p*m, destroys p, const: m
994static inline poly p_Mult_mm(poly p, poly m, const ring r)
995{
996  if (p_LmIsConstant(m, r))
997    return p_Mult_nn(p, pGetCoeff(m), r);
998  else
999    return r->p_Procs->p_Mult_mm(p, m, r);
1000}
1001
1002// return p - m*Copy(q), destroys p; const: p,m
1003static inline poly p_Minus_mm_Mult_qq(poly p, poly m, poly q, const ring r)
1004{
1005#ifdef HAVE_PLURAL
1006  if (rIsPluralRing(r))
1007  {
1008    int lp, lq;
1009    poly spNoether;
1010    return nc_p_Minus_mm_Mult_qq(p, m, q, lp, lq, spNoether, r);
1011  }
1012#endif
1013
1014  int shorter;
1015  poly last;
1016
1017  return r->p_Procs->p_Minus_mm_Mult_qq(p, m, q, shorter, NULL, r, last); // !!!
1018}
1019
1020// like p_Minus_mm_Mult_qq, except that if lp == pLength(lp) lq == pLength(lq)
1021// then lp == pLength(p -m*q)
1022static inline poly p_Minus_mm_Mult_qq(poly p, poly m, poly q, int &lp, int lq,
1023                                 poly spNoether, const ring r)
1024{
1025#ifdef HAVE_PLURAL
1026  if (rIsPluralRing(r))
1027     return nc_p_Minus_mm_Mult_qq(p, m, q, lp, lq, spNoether, r);
1028#endif
1029
1030  int shorter;
1031  poly last,res;
1032  res = r->p_Procs->p_Minus_mm_Mult_qq(p, m, q, shorter, spNoether, r, last);
1033  lp = (lp + lq) - shorter;
1034  return res;
1035}
1036
1037// returns p*Coeff(m) for such monomials pm of p, for which m is divisble by pm
1038static inline poly pp_Mult_Coeff_mm_DivSelect(poly p, const poly m, const ring r)
1039{
1040  int shorter;
1041  return r->p_Procs->pp_Mult_Coeff_mm_DivSelect(p, m, shorter, r);
1042}
1043
1044// returns p*Coeff(m) for such monomials pm of p, for which m is divisble by pm
1045// if lp is length of p on input then lp is length of returned poly on output
1046static inline poly pp_Mult_Coeff_mm_DivSelect(poly p, int &lp, const poly m, const ring r)
1047{
1048  int shorter;
1049  poly pp = r->p_Procs->pp_Mult_Coeff_mm_DivSelect(p, m, shorter, r);
1050  lp -= shorter;
1051  return pp;
1052}
1053
1054// returns -p, destroys p
1055static inline poly p_Neg(poly p, const ring r)
1056{
1057  return r->p_Procs->p_Neg(p, r);
1058}
1059
1060extern poly  _p_Mult_q(poly p, poly q, const int copy, const ring r);
1061// returns p*q, destroys p and q
1062static inline poly p_Mult_q(poly p, poly q, const ring r)
1063{
1064  if (p == NULL)
1065  {
1066    r->p_Procs->p_Delete(&q, r);
1067    return NULL;
1068  }
1069  if (q == NULL)
1070  {
1071    r->p_Procs->p_Delete(&p, r);
1072    return NULL;
1073  }
1074
1075  if (pNext(p) == NULL)
1076  {
1077#ifdef HAVE_PLURAL
1078    if (rIsPluralRing(r))
1079      q = nc_mm_Mult_p(p, q, r);
1080    else
1081#endif /* HAVE_PLURAL */
1082      q = r->p_Procs->p_Mult_mm(q, p, r);
1083
1084    r->p_Procs->p_Delete(&p, r);
1085    return q;
1086  }
1087
1088  if (pNext(q) == NULL)
1089  {
1090  // NEEDED
1091#ifdef HAVE_PLURAL
1092/*    if (rIsPluralRing(r))
1093      p = gnc_p_Mult_mm(p, q, r); // ???
1094    else*/
1095#endif /* HAVE_PLURAL */
1096      p = r->p_Procs->p_Mult_mm(p, q, r);
1097
1098    r->p_Procs->p_Delete(&q, r);
1099    return p;
1100  }
1101#ifdef HAVE_PLURAL
1102  if (rIsPluralRing(r))
1103    return _nc_p_Mult_q(p, q, r);
1104  else
1105#endif
1106  return _p_Mult_q(p, q, 0, r);
1107}
1108
1109// returns p*q, does neither destroy p nor q
1110static inline poly pp_Mult_qq(poly p, poly q, const ring r)
1111{
1112  poly last;
1113  if (p == NULL || q == NULL) return NULL;
1114
1115  if (pNext(p) == NULL)
1116  {
1117#ifdef HAVE_PLURAL
1118    if (rIsPluralRing(r))
1119      return nc_mm_Mult_pp(p, q, r);
1120#endif
1121    return r->p_Procs->pp_Mult_mm(q, p, r, last);
1122  }
1123
1124  if (pNext(q) == NULL)
1125  {
1126    return r->p_Procs->pp_Mult_mm(p, q, r, last);
1127  }
1128
1129  poly qq = q;
1130  if (p == q)
1131    qq = p_Copy(q, r);
1132
1133  poly res;
1134#ifdef HAVE_PLURAL
1135  if (rIsPluralRing(r))
1136    res = _nc_pp_Mult_qq(p, qq, r);
1137  else
1138#endif
1139    res = _p_Mult_q(p, qq, 1, r);
1140
1141  if (qq != q)
1142    p_Delete(&qq, r);
1143  return res;
1144}
1145
1146// returns p + m*q destroys p, const: q, m
1147static inline poly p_Plus_mm_Mult_qq(poly p, poly m, poly q, int &lp, int lq,
1148                                const ring r)
1149{
1150#ifdef HAVE_PLURAL
1151  if (rIsPluralRing(r))
1152    return nc_p_Plus_mm_Mult_qq(p, m, q, lp, lq, r);
1153#endif
1154
1155// this should be implemented more efficiently
1156  poly res, last;
1157  int shorter;
1158  number n_old = pGetCoeff(m);
1159  number n_neg = n_Copy(n_old, r->cf);
1160  n_neg = n_Neg(n_neg, r->cf);
1161  pSetCoeff0(m, n_neg);
1162  res = r->p_Procs->p_Minus_mm_Mult_qq(p, m, q, shorter, NULL, r, last);
1163  lp = (lp + lq) - shorter;
1164  pSetCoeff0(m, n_old);
1165  n_Delete(&n_neg, r->cf);
1166  return res;
1167}
1168
1169static inline poly p_Plus_mm_Mult_qq(poly p, poly m, poly q, const ring r)
1170{
1171  int lp = 0, lq = 0;
1172  return p_Plus_mm_Mult_qq(p, m, q, lp, lq, r);
1173}
1174
1175// returns merged p and q, assumes p and q have no monomials which are equal
1176static inline poly p_Merge_q(poly p, poly q, const ring r)
1177{
1178  return r->p_Procs->p_Merge_q(p, q, r);
1179}
1180
1181// like p_SortMerge, except that p may have equal monimals
1182static inline poly p_SortAdd(poly p, const ring r, BOOLEAN revert= FALSE)
1183{
1184  if (revert) p = pReverse(p);
1185  return sBucketSortAdd(p, r);
1186}
1187
1188// sorts p using bucket sort: returns sorted poly
1189// assumes that monomials of p are all different
1190// reverses it first, if revert == TRUE, use this if input p is "almost" sorted
1191// correctly
1192static inline poly p_SortMerge(poly p, const ring r, BOOLEAN revert= FALSE)
1193{
1194  if (revert) p = pReverse(p);
1195  return sBucketSortMerge(p, r);
1196}
1197
1198/***************************************************************
1199 *
1200 * I/O
1201 *
1202 ***************************************************************/
1203static inline char*     p_String(poly p, ring p_ring)
1204{
1205  return p_String(p, p_ring, p_ring);
1206}
1207static inline char*     p_String0(poly p, ring p_ring)
1208{
1209  return p_String0(p, p_ring, p_ring);
1210}
1211static inline void      p_Write(poly p, ring p_ring)
1212{
1213  p_Write(p, p_ring, p_ring);
1214}
1215static inline void      p_Write0(poly p, ring p_ring)
1216{
1217  p_Write0(p, p_ring, p_ring);
1218}
1219static inline void      p_wrp(poly p, ring p_ring)
1220{
1221  p_wrp(p, p_ring, p_ring);
1222}
1223
1224
1225#if PDEBUG > 0
1226
1227#define _p_LmCmpAction(p, q, r, actionE, actionG, actionS)  \
1228do                                                          \
1229{                                                           \
1230  int _cmp = p_LmCmp(p,q,r);                                \
1231  if (_cmp == 0) actionE;                                   \
1232  if (_cmp == 1) actionG;                                   \
1233  actionS;                                                  \
1234}                                                           \
1235while(0)
1236
1237#else
1238
1239#define _p_LmCmpAction(p, q, r, actionE, actionG, actionS)                      \
1240 p_MemCmp_LengthGeneral_OrdGeneral(p->exp, q->exp, r->CmpL_Size, r->ordsgn,    \
1241                                   actionE, actionG, actionS)
1242
1243#endif
1244
1245#define pDivAssume(x)   ((void)0)
1246
1247
1248
1249/***************************************************************
1250 *
1251 * Allocation/Initalization/Deletion
1252 *
1253 ***************************************************************/
1254// adjustments for negative weights
1255static inline void p_MemAdd_NegWeightAdjust(poly p, const ring r)
1256{
1257  if (r->NegWeightL_Offset != NULL)
1258  {
1259    for (int i=r->NegWeightL_Size-1; i>=0; i--)
1260    {
1261      p->exp[r->NegWeightL_Offset[i]] -= POLY_NEGWEIGHT_OFFSET;
1262    }
1263  }
1264}
1265static inline void p_MemSub_NegWeightAdjust(poly p, const ring r)
1266{
1267  if (r->NegWeightL_Offset != NULL)
1268  {
1269    for (int i=r->NegWeightL_Size-1; i>=0; i--)
1270    {
1271      p->exp[r->NegWeightL_Offset[i]] += POLY_NEGWEIGHT_OFFSET;
1272    }
1273  }
1274}
1275// ExpVextor(d_p) = ExpVector(s_p)
1276static inline void p_ExpVectorCopy(poly d_p, poly s_p, const ring r)
1277{
1278  p_LmCheckPolyRing1(d_p, r);
1279  p_LmCheckPolyRing1(s_p, r);
1280  memcpy(d_p->exp, s_p->exp, r->ExpL_Size*sizeof(long));
1281}
1282
1283static inline poly p_Init(const ring r, omBin bin)
1284{
1285  p_CheckRing1(r);
1286  pAssume1(bin != NULL && r->PolyBin->sizeW == bin->sizeW);
1287  poly p;
1288  omTypeAlloc0Bin(poly, p, bin);
1289  p_MemAdd_NegWeightAdjust(p, r);
1290  p_SetRingOfLm(p, r);
1291  return p;
1292}
1293static inline poly p_Init(const ring r)
1294{
1295  return p_Init(r, r->PolyBin);
1296}
1297
1298static inline poly p_LmInit(poly p, const ring r)
1299{
1300  p_LmCheckPolyRing1(p, r);
1301  poly np;
1302  omTypeAllocBin(poly, np, r->PolyBin);
1303  p_SetRingOfLm(np, r);
1304  memcpy(np->exp, p->exp, r->ExpL_Size*sizeof(long));
1305  pNext(np) = NULL;
1306  pSetCoeff0(np, NULL);
1307  return np;
1308}
1309static inline poly p_LmInit(poly s_p, const ring s_r, const ring d_r, omBin d_bin)
1310{
1311  p_LmCheckPolyRing1(s_p, s_r);
1312  p_CheckRing(d_r);
1313  pAssume1(d_r->N <= s_r->N);
1314  poly d_p = p_Init(d_r, d_bin);
1315  for (int i=d_r->N; i>0; i--)
1316  {
1317    p_SetExp(d_p, i, p_GetExp(s_p, i,s_r), d_r);
1318  }
1319  if (rRing_has_Comp(d_r))
1320  {
1321    p_SetComp(d_p, p_GetComp(s_p,s_r), d_r);
1322  }
1323  p_Setm(d_p, d_r);
1324  return d_p;
1325}
1326static inline poly p_LmInit(poly s_p, const ring s_r, const ring d_r)
1327{
1328  pAssume1(d_r != NULL);
1329  return p_LmInit(s_p, s_r, d_r, d_r->PolyBin);
1330}
1331
1332// set all exponents l..k to 0, assume exp. k+1..n and 1..l-1 are in
1333// different blocks
1334// set coeff to 1
1335static inline poly p_GetExp_k_n(poly p, int l, int k, const ring r)
1336{
1337  if (p == NULL) return NULL;
1338  p_LmCheckPolyRing1(p, r);
1339  poly np;
1340  omTypeAllocBin(poly, np, r->PolyBin);
1341  p_SetRingOfLm(np, r);
1342  memcpy(np->exp, p->exp, r->ExpL_Size*sizeof(long));
1343  pNext(np) = NULL;
1344  pSetCoeff0(np, n_Init(1, r->cf));
1345  int i;
1346  for(i=l;i<=k;i++)
1347  {
1348    //np->exp[(r->VarOffset[i] & 0xffffff)] =0;
1349    p_SetExp(np,i,0,r);
1350  }
1351  p_Setm(np,r);
1352  return np;
1353}
1354
1355// simialar to p_ShallowCopyDelete but does it only for leading monomial
1356static inline poly p_LmShallowCopyDelete(poly p, const ring r)
1357{
1358  p_LmCheckPolyRing1(p, r);
1359  pAssume1(bin->sizeW == r->PolyBin->sizeW);
1360  poly new_p = p_New(r);
1361  memcpy(new_p->exp, p->exp, r->ExpL_Size*sizeof(long));
1362  pSetCoeff0(new_p, pGetCoeff(p));
1363  pNext(new_p) = pNext(p);
1364  omFreeBinAddr(p);
1365  return new_p;
1366}
1367
1368/***************************************************************
1369 *
1370 * Operation on ExpVectors
1371 *
1372 ***************************************************************/
1373// ExpVector(p1) += ExpVector(p2)
1374static inline void p_ExpVectorAdd(poly p1, poly p2, const ring r)
1375{
1376  p_LmCheckPolyRing1(p1, r);
1377  p_LmCheckPolyRing1(p2, r);
1378#if PDEBUG >= 1
1379  for (int i=1; i<=r->N; i++)
1380    pAssume1((unsigned long) (p_GetExp(p1, i, r) + p_GetExp(p2, i, r)) <= r->bitmask);
1381  pAssume1(p_GetComp(p1, r) == 0 || p_GetComp(p2, r) == 0);
1382#endif
1383
1384  p_MemAdd_LengthGeneral(p1->exp, p2->exp, r->ExpL_Size);
1385  p_MemAdd_NegWeightAdjust(p1, r);
1386}
1387// ExpVector(pr) = ExpVector(p1) + ExpVector(p2)
1388static inline void p_ExpVectorSum(poly pr, poly p1, poly p2, const ring r)
1389{
1390  p_LmCheckPolyRing1(p1, r);
1391  p_LmCheckPolyRing1(p2, r);
1392  p_LmCheckPolyRing1(pr, r);
1393#if PDEBUG >= 1
1394  for (int i=1; i<=r->N; i++)
1395    pAssume1((unsigned long) (p_GetExp(p1, i, r) + p_GetExp(p2, i, r)) <= r->bitmask);
1396  pAssume1(p_GetComp(p1, r) == 0 || p_GetComp(p2, r) == 0);
1397#endif
1398
1399  p_MemSum_LengthGeneral(pr->exp, p1->exp, p2->exp, r->ExpL_Size);
1400  p_MemAdd_NegWeightAdjust(pr, r);
1401}
1402// ExpVector(p1) -= ExpVector(p2)
1403static inline void p_ExpVectorSub(poly p1, poly p2, const ring r)
1404{
1405  p_LmCheckPolyRing1(p1, r);
1406  p_LmCheckPolyRing1(p2, r);
1407#if PDEBUG >= 1
1408  for (int i=1; i<=r->N; i++)
1409    pAssume1(p_GetExp(p1, i, r) >= p_GetExp(p2, i, r));
1410  pAssume1(p_GetComp(p1, r) == 0 || p_GetComp(p2, r) == 0 ||
1411          p_GetComp(p1, r) == p_GetComp(p2, r));
1412#endif
1413
1414  p_MemSub_LengthGeneral(p1->exp, p2->exp, r->ExpL_Size);
1415  p_MemSub_NegWeightAdjust(p1, r);
1416
1417}
1418// ExpVector(p1) += ExpVector(p2) - ExpVector(p3)
1419//static inline void p_ExpVectorAddSub(poly p1, poly p2, poly p3, const ring r)
1420//{
1421//  p_LmCheckPolyRing1(p1, r);
1422//  p_LmCheckPolyRing1(p2, r);
1423//  p_LmCheckPolyRing1(p3, r);
1424//#if PDEBUG >= 1
1425//  for (int i=1; i<=r->N; i++)
1426//    pAssume1(p_GetExp(p1, i, r) + p_GetExp(p2, i, r) >= p_GetExp(p3, i, r));
1427//  pAssume1(p_GetComp(p1, r) == 0 ||
1428//           (p_GetComp(p2, r) - p_GetComp(p3, r) == 0) ||
1429//           (p_GetComp(p1, r) == p_GetComp(p2, r) - p_GetComp(p3, r)));
1430//#endif
1431//
1432//  p_MemAddSub_LengthGeneral(p1->exp, p2->exp, p3->exp, r->ExpL_Size);
1433//  // no need to adjust in case of NegWeights
1434//}
1435
1436// ExpVector(pr) = ExpVector(p1) - ExpVector(p2)
1437static inline void p_ExpVectorDiff(poly pr, poly p1, poly p2, const ring r)
1438{
1439  p_LmCheckPolyRing1(p1, r);
1440  p_LmCheckPolyRing1(p2, r);
1441  p_LmCheckPolyRing1(pr, r);
1442#if PDEBUG >= 2
1443  for (int i=1; i<=r->N; i++)
1444    pAssume1(p_GetExp(p1, i, r) >= p_GetExp(p2, i, r));
1445  pAssume1(!rRing_has_Comp(r) || p_GetComp(p1, r) == p_GetComp(p2, r));
1446#endif
1447
1448  p_MemDiff_LengthGeneral(pr->exp, p1->exp, p2->exp, r->ExpL_Size);
1449  p_MemSub_NegWeightAdjust(pr, r);
1450}
1451
1452static inline BOOLEAN p_ExpVectorEqual(poly p1, poly p2, const ring r)
1453{
1454  p_LmCheckPolyRing1(p1, r);
1455  p_LmCheckPolyRing1(p2, r);
1456
1457  int i = r->ExpL_Size;
1458  unsigned long *ep = p1->exp;
1459  unsigned long *eq = p2->exp;
1460
1461  do
1462  {
1463    i--;
1464    if (ep[i] != eq[i]) return FALSE;
1465  }
1466  while (i);
1467  return TRUE;
1468}
1469
1470static inline long p_Totaldegree(poly p, const ring r)
1471{
1472  p_LmCheckPolyRing1(p, r);
1473  unsigned long s = p_GetTotalDegree(p->exp[r->VarL_Offset[0]],
1474                                     r,
1475                                     r->MinExpPerLong);
1476  for (int i=r->VarL_Size-1; i>0; i--)
1477  {
1478    s += p_GetTotalDegree(p->exp[r->VarL_Offset[i]], r);
1479  }
1480  return (long)s;
1481}
1482
1483static inline void p_GetExpV(poly p, int *ev, const ring r)
1484{
1485  p_LmCheckPolyRing1(p, r);
1486  for (int j = r->N; j; j--)
1487      ev[j] = p_GetExp(p, j, r);
1488
1489  ev[0] = p_GetComp(p, r);
1490}
1491static inline void p_SetExpV(poly p, int *ev, const ring r)
1492{
1493  p_LmCheckPolyRing1(p, r);
1494  for (int j = r->N; j; j--)
1495      p_SetExp(p, j, ev[j], r);
1496
1497  p_SetComp(p, ev[0],r);
1498  p_Setm(p, r);
1499}
1500
1501/***************************************************************
1502 *
1503 * Comparison w.r.t. monomial ordering
1504 *
1505 ***************************************************************/
1506
1507static inline int p_LmCmp(poly p, poly q, const ring r)
1508{
1509  p_LmCheckPolyRing1(p, r);
1510  p_LmCheckPolyRing1(q, r);
1511
1512  const unsigned long* _s1 = ((unsigned long*) p->exp);
1513  const unsigned long* _s2 = ((unsigned long*) q->exp);
1514  register unsigned long _v1;
1515  register unsigned long _v2;
1516  const unsigned long _l = r->CmpL_Size;
1517
1518  register unsigned long _i=0;
1519
1520  LengthGeneral_OrdGeneral_LoopTop:
1521  _v1 = _s1[_i];
1522  _v2 = _s2[_i];
1523  if (_v1 == _v2)
1524  {
1525    _i++;
1526    if (_i == _l) return 0;
1527    goto LengthGeneral_OrdGeneral_LoopTop;
1528  }
1529  const long* _ordsgn = (long*) r->ordsgn;
1530  if (_v1 > _v2)
1531  {
1532    if (_ordsgn[_i] == 1) return 1;
1533    return -1;
1534  }
1535  if (_ordsgn[_i] == 1) return -1;
1536  return 1;
1537
1538}
1539
1540/// returns TRUE if p1 is a skalar multiple of p2
1541/// assume p1 != NULL and p2 != NULL
1542BOOLEAN p_ComparePolys(poly p1,poly p2, const ring r);
1543
1544
1545/***************************************************************
1546 *
1547 * Comparisons: they are all done without regarding coeffs
1548 *
1549 ***************************************************************/
1550#define p_LmCmpAction(p, q, r, actionE, actionG, actionS) \
1551  _p_LmCmpAction(p, q, r, actionE, actionG, actionS)
1552
1553// returns 1 if ExpVector(p)==ExpVector(q): does not compare numbers !!
1554#define p_LmEqual(p1, p2, r) p_ExpVectorEqual(p1, p2, r)
1555
1556// pCmp: args may be NULL
1557// returns: (p2==NULL ? 1 : (p1 == NULL ? -1 : p_LmCmp(p1, p2)))
1558static inline int p_Cmp(poly p1, poly p2, ring r)
1559{
1560  if (p2==NULL)
1561    return 1;
1562  if (p1==NULL)
1563    return -1;
1564  return p_LmCmp(p1,p2,r);
1565}
1566
1567
1568/***************************************************************
1569 *
1570 * divisibility
1571 *
1572 ***************************************************************/
1573// return: FALSE, if there exists i, such that a->exp[i] > b->exp[i]
1574//         TRUE, otherwise
1575// (1) Consider long vars, instead of single exponents
1576// (2) Clearly, if la > lb, then FALSE
1577// (3) Suppose la <= lb, and consider first bits of single exponents in l:
1578//     if TRUE, then value of these bits is la ^ lb
1579//     if FALSE, then la-lb causes an "overflow" into one of those bits, i.e.,
1580//               la ^ lb != la - lb
1581static inline BOOLEAN _p_LmDivisibleByNoComp(poly a, poly b, const ring r)
1582{
1583  int i=r->VarL_Size - 1;
1584  unsigned long divmask = r->divmask;
1585  unsigned long la, lb;
1586
1587  if (r->VarL_LowIndex >= 0)
1588  {
1589    i += r->VarL_LowIndex;
1590    do
1591    {
1592      la = a->exp[i];
1593      lb = b->exp[i];
1594      if ((la > lb) ||
1595          (((la & divmask) ^ (lb & divmask)) != ((lb - la) & divmask)))
1596      {
1597        pDivAssume(p_DebugLmDivisibleByNoComp(a, b, r) == FALSE);
1598        return FALSE;
1599      }
1600      i--;
1601    }
1602    while (i>=r->VarL_LowIndex);
1603  }
1604  else
1605  {
1606    do
1607    {
1608      la = a->exp[r->VarL_Offset[i]];
1609      lb = b->exp[r->VarL_Offset[i]];
1610      if ((la > lb) ||
1611          (((la & divmask) ^ (lb & divmask)) != ((lb - la) & divmask)))
1612      {
1613        pDivAssume(p_DebugLmDivisibleByNoComp(a, b, r) == FALSE);
1614        return FALSE;
1615      }
1616      i--;
1617    }
1618    while (i>=0);
1619  }
1620#ifdef HAVE_RINGS
1621  pDivAssume(p_DebugLmDivisibleByNoComp(a, b, r) == nDivBy(p_GetCoeff(b, r), p_GetCoeff(a, r)));
1622  return (!rField_is_Ring(r)) || n_DivBy(p_GetCoeff(b, r), p_GetCoeff(a, r), r->cf);
1623#else
1624  pDivAssume(p_DebugLmDivisibleByNoComp(a, b, r) == TRUE);
1625  return TRUE;
1626#endif
1627}
1628
1629static inline BOOLEAN _p_LmDivisibleByNoComp(poly a, const ring r_a, poly b, const ring r_b)
1630{
1631  int i=r_a->N;
1632  pAssume1(r_a->N == r_b->N);
1633
1634  do
1635  {
1636    if (p_GetExp(a,i,r_a) > p_GetExp(b,i,r_b))
1637      return FALSE;
1638    i--;
1639  }
1640  while (i);
1641#ifdef HAVE_RINGS
1642  return n_DivBy(p_GetCoeff(b, r_b), p_GetCoeff(a, r_a), r_a->cf);
1643#else
1644  return TRUE;
1645#endif
1646}
1647
1648#ifdef HAVE_RATGRING
1649static inline BOOLEAN _p_LmDivisibleByNoCompPart(poly a, const ring r_a, poly b, const ring r_b,const int start, const int end)
1650{
1651  int i=end;
1652  pAssume1(r_a->N == r_b->N);
1653
1654  do
1655  {
1656    if (p_GetExp(a,i,r_a) > p_GetExp(b,i,r_b))
1657      return FALSE;
1658    i--;
1659  }
1660  while (i>=start);
1661#ifdef HAVE_RINGS
1662  return nDivBy(p_GetCoeff(b, r), p_GetCoeff(a, r));
1663#else
1664  return TRUE;
1665#endif
1666}
1667static inline BOOLEAN _p_LmDivisibleByPart(poly a, const ring r_a, poly b, const ring r_b,const int start, const int end)
1668{
1669  if (p_GetComp(a, r_a) == 0 || p_GetComp(a,r_a) == p_GetComp(b,r_b))
1670    return _p_LmDivisibleByNoCompPart(a, r_a, b, r_b,start,end);
1671  return FALSE;
1672}
1673static inline BOOLEAN p_LmDivisibleByPart(poly a, poly b, const ring r,const int start, const int end)
1674{
1675  p_LmCheckPolyRing1(b, r);
1676  pIfThen1(a != NULL, p_LmCheckPolyRing1(b, r));
1677  if (p_GetComp(a, r) == 0 || p_GetComp(a,r) == p_GetComp(b,r))
1678    return _p_LmDivisibleByNoCompPart(a, r, b, r,start, end);
1679  return FALSE;
1680}
1681#endif
1682static inline BOOLEAN _p_LmDivisibleBy(poly a, poly b, const ring r)
1683{
1684  if (p_GetComp(a, r) == 0 || p_GetComp(a,r) == p_GetComp(b,r))
1685    return _p_LmDivisibleByNoComp(a, b, r);
1686  return FALSE;
1687}
1688static inline BOOLEAN _p_LmDivisibleBy(poly a, const ring r_a, poly b, const ring r_b)
1689{
1690  if (p_GetComp(a, r_a) == 0 || p_GetComp(a,r_a) == p_GetComp(b,r_b))
1691    return _p_LmDivisibleByNoComp(a, r_a, b, r_b);
1692  return FALSE;
1693}
1694static inline BOOLEAN p_LmDivisibleByNoComp(poly a, poly b, const ring r)
1695{
1696  p_LmCheckPolyRing1(a, r);
1697  p_LmCheckPolyRing1(b, r);
1698  return _p_LmDivisibleByNoComp(a, b, r);
1699}
1700static inline BOOLEAN p_LmDivisibleBy(poly a, poly b, const ring r)
1701{
1702  p_LmCheckPolyRing1(b, r);
1703  pIfThen1(a != NULL, p_LmCheckPolyRing1(b, r));
1704  if (p_GetComp(a, r) == 0 || p_GetComp(a,r) == p_GetComp(b,r))
1705    return _p_LmDivisibleByNoComp(a, b, r);
1706  return FALSE;
1707}
1708
1709static inline BOOLEAN p_DivisibleBy(poly a, poly b, const ring r)
1710{
1711  pIfThen1(b!=NULL, p_LmCheckPolyRing1(b, r));
1712  pIfThen1(a!=NULL, p_LmCheckPolyRing1(a, r));
1713
1714  if (a != NULL && (p_GetComp(a, r) == 0 || p_GetComp(a,r) == p_GetComp(b,r)))
1715      return _p_LmDivisibleByNoComp(a,b,r);
1716  return FALSE;
1717}
1718static inline BOOLEAN p_DivisibleBy(poly a, const ring r_a, poly b, const ring r_b)
1719{
1720  pIfThen1(b!=NULL, p_LmCheckPolyRing1(b, r_b));
1721  pIfThen1(a!=NULL, p_LmCheckPolyRing1(a, r_a));
1722  if (a != NULL) {
1723      return _p_LmDivisibleBy(a, r_a, b, r_b);
1724  }
1725  return FALSE;
1726}
1727static inline BOOLEAN p_LmDivisibleBy(poly a, const ring r_a, poly b, const ring r_b)
1728{
1729  p_LmCheckPolyRing(a, r_a);
1730  p_LmCheckPolyRing(b, r_b);
1731  return _p_LmDivisibleBy(a, r_a, b, r_b);
1732}
1733static inline BOOLEAN p_LmShortDivisibleBy(poly a, unsigned long sev_a,
1734                                    poly b, unsigned long not_sev_b, const ring r)
1735{
1736  p_LmCheckPolyRing1(a, r);
1737  p_LmCheckPolyRing1(b, r);
1738#ifndef PDIV_DEBUG
1739  _pPolyAssume2(p_GetShortExpVector(a, r) == sev_a, a, r);
1740  _pPolyAssume2(p_GetShortExpVector(b, r) == ~ not_sev_b, b, r);
1741
1742  if (sev_a & not_sev_b)
1743  {
1744    pAssume1(p_LmDivisibleByNoComp(a, b, r) == FALSE);
1745    return FALSE;
1746  }
1747  return p_LmDivisibleBy(a, b, r);
1748#else
1749  return pDebugLmShortDivisibleBy(a, sev_a, r, b, not_sev_b, r);
1750#endif
1751}
1752
1753static inline BOOLEAN p_LmShortDivisibleBy(poly a, unsigned long sev_a, const ring r_a,
1754                                      poly b, unsigned long not_sev_b, const ring r_b)
1755{
1756  p_LmCheckPolyRing1(a, r_a);
1757  p_LmCheckPolyRing1(b, r_b);
1758#ifndef PDIV_DEBUG
1759  _pPolyAssume2(p_GetShortExpVector(a, r_a) == sev_a, a, r_a);
1760  _pPolyAssume2(p_GetShortExpVector(b, r_b) == ~ not_sev_b, b, r_b);
1761
1762  if (sev_a & not_sev_b)
1763  {
1764    pAssume1(_p_LmDivisibleByNoComp(a, r_a, b, r_b) == FALSE);
1765    return FALSE;
1766  }
1767  return _p_LmDivisibleBy(a, r_a, b, r_b);
1768#else
1769  return pDebugLmShortDivisibleBy(a, sev_a, r_a, b, not_sev_b, r_b);
1770#endif
1771}
1772
1773/***************************************************************
1774 *
1775 * Misc things on Lm
1776 *
1777 ***************************************************************/
1778
1779
1780// like the respective p_LmIs* routines, except that p might be empty
1781static inline BOOLEAN p_IsConstantComp(const poly p, const ring r)
1782{
1783  if (p == NULL) return TRUE;
1784  return (pNext(p)==NULL) && p_LmIsConstantComp(p, r);
1785}
1786
1787static inline BOOLEAN p_IsConstant(const poly p, const ring r)
1788{
1789  if (p == NULL) return TRUE;
1790  return (pNext(p)==NULL) && p_LmIsConstant(p, r);
1791}
1792
1793static inline BOOLEAN p_IsConstantPoly(const poly p, const ring r)
1794{
1795  poly pp=p;
1796  while(pp!=NULL)
1797  {
1798    if (! p_LmIsConstantComp(pp, r))
1799      return FALSE;
1800    pIter(pp);
1801  }
1802  return TRUE;
1803}
1804
1805static inline BOOLEAN p_IsUnit(const poly p, const ring r)
1806{
1807  if (p == NULL) return FALSE;
1808#ifdef HAVE_RINGS
1809  if (rField_is_Ring(r))
1810    return (p_LmIsConstant(p, r) && n_IsUnit(pGetCoeff(p),r->cf));
1811#endif
1812  return p_LmIsConstant(p, r);
1813}
1814
1815static inline BOOLEAN p_LmExpVectorAddIsOk(const poly p1, const poly p2,
1816                                      const ring r)
1817{
1818  p_LmCheckPolyRing(p1, r);
1819  p_LmCheckPolyRing(p2, r);
1820  unsigned long l1, l2, divmask = r->divmask;
1821  int i;
1822
1823  for (i=0; i<r->VarL_Size; i++)
1824  {
1825    l1 = p1->exp[r->VarL_Offset[i]];
1826    l2 = p2->exp[r->VarL_Offset[i]];
1827    // do the divisiblity trick
1828    if ( (l1 > ULONG_MAX - l2) ||
1829         (((l1 & divmask) ^ (l2 & divmask)) != ((l1 + l2) & divmask)))
1830      return FALSE;
1831  }
1832  return TRUE;
1833}
1834void      p_Split(poly p, poly * r);   /*p => IN(p), r => REST(p) */
1835BOOLEAN p_HasNotCF(poly p1, poly p2, const ring r);
1836poly      p_mInit(const char *s, BOOLEAN &ok, const ring r); /* monom s -> poly, interpreter */
1837const char *    p_Read(const char *s, poly &p,const ring r); /* monom -> poly */
1838poly      p_Divide(poly a, poly b, const ring r);
1839poly      p_DivideM(poly a, poly b, const ring r);
1840poly      p_Div_nn(poly p, const number n, const ring r);
1841void      p_Lcm(poly a, poly b, poly m, const ring r);
1842poly      p_Diff(poly a, int k, const ring r);
1843poly      p_DiffOp(poly a, poly b,BOOLEAN multiply, const ring r);
1844int       p_Weight(int c, const ring r);
1845
1846/* assumes that p and divisor are univariate polynomials in r,
1847   mentioning the same variable;
1848   assumes divisor != NULL;
1849   p may be NULL;
1850   assumes a global monomial ordering in r;
1851   performs polynomial division of p by divisor:
1852     - afterwards p contains the remainder of the division, i.e.,
1853       p_before = result * divisor + p_afterwards;
1854     - if needResult == TRUE, then the method computes and returns 'result',
1855       otherwise NULL is returned (This parametrization can be used when
1856       one is only interested in the remainder of the division. In this
1857       case, the method will be slightly faster.)
1858   leaves divisor unmodified */
1859poly      p_PolyDiv(poly &p, poly divisor, BOOLEAN needResult, ring r);
1860
1861/* returns NULL if p == NULL, otherwise makes p monic by dividing
1862   by its leading coefficient (only done if this is not already 1);
1863   this assumes that we are over a ground field so that division
1864   is well-defined;
1865   modifies p */
1866void      p_Monic(poly &p, ring r);
1867
1868/* assumes that p and q are univariate polynomials in r,
1869   mentioning the same variable;
1870   assumes a global monomial ordering in r;
1871   assumes that not both p and q are NULL;
1872   returns the gcd of p and q;
1873   leaves p and q unmodified */
1874poly      p_Gcd(poly p, poly q, ring r);
1875
1876/* assumes that p and q are univariate polynomials in r,
1877   mentioning the same variable;
1878   assumes a global monomial ordering in r;
1879   assumes that not both p and q are NULL;
1880   returns the gcd of p and q;
1881   moreover, afterwards pFactor and qFactor contain appropriate
1882   factors such that gcd(p, q) = p * pFactor + q * qFactor;
1883   leaves p and q unmodified */
1884poly      p_ExtGcd(poly p, poly &pFactor, poly q, poly &qFactor, ring r);
1885
1886/* syszygy stuff */
1887BOOLEAN   p_VectorHasUnitB(poly p, int * k, const ring r);
1888void      p_VectorHasUnit(poly p, int * k, int * len, const ring r);
1889poly      p_TakeOutComp1(poly * p, int k, const ring r);
1890// Splits *p into two polys: *q which consists of all monoms with
1891// component == comp and *p of all other monoms *lq == pLength(*q)
1892// On return all components pf *q == 0
1893void p_TakeOutComp(poly *p, long comp, poly *q, int *lq, const ring r);
1894
1895// This is something weird -- Don't use it, unless you know what you are doing
1896poly      p_TakeOutComp(poly * p, int k);
1897
1898void      p_DeleteComp(poly * p,int k, const ring r);
1899
1900/*-------------ring management:----------------------*/
1901void p_SetGlobals(const ring r, BOOLEAN complete = TRUE);
1902
1903// resets the pFDeg and pLDeg: if pLDeg is not given, it is
1904// set to currRing->pLDegOrig, i.e. to the respective LDegProc which
1905// only uses pFDeg (and not pDeg, or pTotalDegree, etc).
1906// If you use this, make sure your procs does not make any assumptions
1907// on ordering and/or OrdIndex -- otherwise they might return wrong results
1908// on strat->tailRing
1909void pSetDegProcs(ring r, pFDegProc new_FDeg, pLDegProc new_lDeg = NULL);
1910// restores pFDeg and pLDeg:
1911void pRestoreDegProcs(ring r, pFDegProc old_FDeg, pLDegProc old_lDeg);
1912
1913/*-------------pComp for syzygies:-------------------*/
1914void p_SetModDeg(intvec *w, ring r);
1915
1916/*------------ Jet ----------------------------------*/
1917poly pp_Jet(poly p, int m, const ring R);
1918poly p_Jet(poly p, int m,const ring R);
1919poly pp_JetW(poly p, int m, short *w, const ring R);
1920poly p_JetW(poly p, int m, short *w, const ring R);
1921
1922
1923poly      p_PermPoly (poly p, int * perm,const ring OldRing, const ring dst,
1924                     nMapFunc nMap, int *par_perm=NULL, int OldPar=0);
1925
1926/*----------------------------------------------------*/
1927poly p_Series(int n,poly p,poly u, intvec *w, const ring R);
1928poly p_Invers(int n,poly u,intvec *w, const ring R);
1929
1930
1931
1932/*----------------------------------------------------*/
1933int   p_Var(poly mi,const ring r);
1934
1935
1936#endif // P_POLYS_H
1937
Note: See TracBrowser for help on using the repository browser.