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

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