source: git/libpolys/polys/monomials/p_polys.h @ 4a4e29

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