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

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