source: git/libpolys/polys/monomials/p_polys.h @ 922962

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