source: git/polys/polys.cc @ fb4075b

spielwiese
Last change on this file since fb4075b was fb4075b, checked in by Hans Schoenemann <hannes@…>, 13 years ago
moved p_Divide, p_DivideM to p_polys
  • Property mode set to 100644
File size: 15.5 KB
Line 
1/****************************************
2*  Computer Algebra System SINGULAR     *
3****************************************/
4/* $Id$ */
5
6/*
7* ABSTRACT - all basic methods to manipulate polynomials
8*/
9
10/* includes */
11#include <stdio.h>
12#include <string.h>
13#include <ctype.h>
14#include <auxiliary.h>
15#include "options.h"
16#include "omalloc.h"
17#include "reporter.h"
18#include "numbers.h"
19#include "polys.h"
20#include "ring.h"
21
22#ifdef HAVE_PLURAL
23#include <gring.h>
24#include <sca.h>
25#endif
26
27/* ----------- global variables, set by pSetGlobals --------------------- */
28/* computes length and maximal degree of a POLYnomial */
29pLDegProc pLDeg;
30/* computes the degree of the initial term, used for std */
31pFDegProc pFDeg;
32/* the monomial ordering of the head monomials a and b */
33/* returns -1 if a comes before b, 0 if a=b, 1 otherwise */
34
35/* 1 for polynomial ring, -1 otherwise */
36int     pOrdSgn;
37// it is of type int, not BOOLEAN because it is also in ip
38/* TRUE if the monomial ordering is not compatible with pFDeg */
39BOOLEAN pLexOrder;
40
41/* ----------- global variables, set by procedures from hecke/kstd1 ----- */
42/* the highest monomial below pHEdge */
43poly      ppNoether = NULL;
44
45/* -------------------------------------------------------- */
46/*2
47* change all global variables to fit the description of the new ring
48*/
49
50
51void pSetGlobals(const ring r, BOOLEAN complete)
52{
53  if (ppNoether!=NULL) pDelete(&ppNoether);
54  //pOrdSgn = r->OrdSgn;
55  //pFDeg=r->pFDeg;
56  //pLDeg=r->pLDeg;
57  //pLexOrder=r->LexOrder;
58
59  if (complete)
60  {
61    test &= ~ TEST_RINGDEP_OPTS;
62    test |= r->options;
63  }
64}
65
66// resets the pFDeg and pLDeg: if pLDeg is not given, it is
67// set to currRing->pLDegOrig, i.e. to the respective LDegProc which
68// only uses pFDeg (and not pDeg, or pTotalDegree, etc)
69void pSetDegProcs(pFDegProc new_FDeg, pLDegProc new_lDeg)
70{
71  assume(new_FDeg != NULL);
72  pFDeg = new_FDeg;
73  currRing->pFDeg = new_FDeg;
74
75  if (new_lDeg == NULL)
76    new_lDeg = currRing->pLDegOrig;
77
78  pLDeg = new_lDeg;
79  currRing->pLDeg = new_lDeg;
80}
81
82
83// restores pFDeg and pLDeg:
84extern void pRestoreDegProcs(pFDegProc old_FDeg, pLDegProc old_lDeg)
85{
86  assume(old_FDeg != NULL && old_lDeg != NULL);
87  pFDeg = old_FDeg;
88  currRing->pFDeg = old_FDeg;
89  pLDeg = old_lDeg;
90  currRing->pLDeg = old_lDeg;
91}
92
93#ifdef HAVE_RINGS   //TODO Oliver
94#define pDiv_nn(p, n)              p_Div_nn(p, n, currRing)
95
96poly p_Div_nn(poly p, const number n, const ring r)
97{
98  pAssume(!n_IsZero(n,r));
99  p_Test(p, r);
100
101  poly q = p;
102  while (p != NULL)
103  {
104    number nc = pGetCoeff(p);
105    pSetCoeff0(p, n_Div(nc, n, r));
106    n_Delete(&nc, r);
107    pIter(p);
108  }
109  p_Test(q, r);
110  return q;
111}
112#endif
113
114#ifdef HAVE_RINGS
115/* TRUE iff LT(f) | LT(g) */
116BOOLEAN pDivisibleByRingCase(poly f, poly g)
117{
118  int exponent;
119  for(int i = (int)pVariables; i; i--)
120  {
121    exponent = pGetExp(g, i) - pGetExp(f, i);
122    if (exponent < 0) return FALSE;
123  }
124  return nDivBy(pGetCoeff(g), pGetCoeff(f));
125}
126#endif
127
128/*2
129* returns the LCM of the head terms of a and b in *m
130*/
131void pLcm(poly a, poly b, poly m)
132{
133  int i;
134  for (i=pVariables; i; i--)
135  {
136    pSetExp(m,i, si_max( pGetExp(a,i), pGetExp(b,i)));
137  }
138  pSetComp(m, si_max(pGetComp(a), pGetComp(b)));
139  /* Don't do a pSetm here, otherwise hres/lres chockes */
140}
141
142BOOLEAN _p_Test(poly p, ring r, int level);
143
144/*2
145*make p homogeneous by multiplying the monomials by powers of x_varnum
146*assume: deg(var(varnum))==1
147*/
148poly pHomogen (poly p, int varnum)
149{
150  pFDegProc deg;
151  if (pLexOrder && (currRing->order[0]==ringorder_lp))
152    deg=p_Totaldegree;
153  else
154    deg=pFDeg;
155
156  poly q=NULL, qn;
157  int  o,ii;
158  sBucket_pt bp;
159
160  if (p!=NULL)
161  {
162    if ((varnum < 1) || (varnum > pVariables))
163    {
164      return NULL;
165    }
166    o=deg(p,currRing);
167    q=pNext(p);
168    while (q != NULL)
169    {
170      ii=deg(q,currRing);
171      if (ii>o) o=ii;
172      pIter(q);
173    }
174    q = pCopy(p);
175    bp = sBucketCreate(currRing);
176    while (q != NULL)
177    {
178      ii = o-deg(q,currRing);
179      if (ii!=0)
180      {
181        pAddExp(q,varnum, (long)ii);
182        pSetm(q);
183      }
184      qn = pNext(q);
185      pNext(q) = NULL;
186      sBucket_Add_p(bp, q, 1);
187      q = qn;
188    }
189    sBucketDestroyAdd(bp, &q, &ii);
190  }
191  return q;
192}
193
194/*----------utilities for syzygies--------------*/
195poly pTakeOutComp(poly * p, int k)
196{
197  poly q = *p,qq=NULL,result = NULL;
198
199  if (q==NULL) return NULL;
200  BOOLEAN use_setmcomp=rOrd_SetCompRequiresSetm(currRing);
201  if (pGetComp(q)==k)
202  {
203    result = q;
204    do
205    {
206      pSetComp(q,0);
207      if (use_setmcomp) pSetmComp(q);
208      qq = q;
209      pIter(q);
210    }
211    while ((q!=NULL) && (pGetComp(q)==k));
212    *p = q;
213    pNext(qq) = NULL;
214  }
215  if (q==NULL) return result;
216  if (pGetComp(q) > k)
217  {
218    pSubComp(q,1);
219    if (use_setmcomp) pSetmComp(q);
220  }
221  poly pNext_q;
222  while ((pNext_q=pNext(q))!=NULL)
223  {
224    if (pGetComp(pNext_q)==k)
225    {
226      if (result==NULL)
227      {
228        result = pNext_q;
229        qq = result;
230      }
231      else
232      {
233        pNext(qq) = pNext_q;
234        pIter(qq);
235      }
236      pNext(q) = pNext(pNext_q);
237      pNext(qq) =NULL;
238      pSetComp(qq,0);
239      if (use_setmcomp) pSetmComp(qq);
240    }
241    else
242    {
243      /*pIter(q);*/ q=pNext_q;
244      if (pGetComp(q) > k)
245      {
246        pSubComp(q,1);
247        if (use_setmcomp) pSetmComp(q);
248      }
249    }
250  }
251  return result;
252}
253
254// Splits *p into two polys: *q which consists of all monoms with
255// component == comp and *p of all other monoms *lq == pLength(*q)
256void pTakeOutComp(poly *r_p, long comp, poly *r_q, int *lq)
257{
258  spolyrec pp, qq;
259  poly p, q, p_prev;
260  int l = 0;
261
262#ifdef HAVE_ASSUME
263  int lp = pLength(*r_p);
264#endif
265
266  pNext(&pp) = *r_p;
267  p = *r_p;
268  p_prev = &pp;
269  q = &qq;
270
271  while(p != NULL)
272  {
273    while (pGetComp(p) == comp)
274    {
275      pNext(q) = p;
276      pIter(q);
277      pSetComp(p, 0);
278      pSetmComp(p);
279      pIter(p);
280      l++;
281      if (p == NULL)
282      {
283        pNext(p_prev) = NULL;
284        goto Finish;
285      }
286    }
287    pNext(p_prev) = p;
288    p_prev = p;
289    pIter(p);
290  }
291
292  Finish:
293  pNext(q) = NULL;
294  *r_p = pNext(&pp);
295  *r_q = pNext(&qq);
296  *lq = l;
297#ifdef HAVE_ASSUME
298  assume(pLength(*r_p) + pLength(*r_q) == lp);
299#endif
300  pTest(*r_p);
301  pTest(*r_q);
302}
303
304#if 1
305poly pTakeOutComp1(poly * p, int k)
306{
307  poly q = *p;
308
309  if (q==NULL) return NULL;
310
311  poly qq=NULL,result = NULL;
312
313  if (pGetComp(q)==k)
314  {
315    result = q; /* *p */
316    while ((q!=NULL) && (pGetComp(q)==k))
317    {
318      pSetComp(q,0);
319      pSetmComp(q);
320      qq = q;
321      pIter(q);
322    }
323    *p = q;
324    pNext(qq) = NULL;
325  }
326  if (q==NULL) return result;
327//  if (pGetComp(q) > k) pGetComp(q)--;
328  while (pNext(q)!=NULL)
329  {
330    if (pGetComp(pNext(q))==k)
331    {
332      if (result==NULL)
333      {
334        result = pNext(q);
335        qq = result;
336      }
337      else
338      {
339        pNext(qq) = pNext(q);
340        pIter(qq);
341      }
342      pNext(q) = pNext(pNext(q));
343      pNext(qq) =NULL;
344      pSetComp(qq,0);
345      pSetmComp(qq);
346    }
347    else
348    {
349      pIter(q);
350//      if (pGetComp(q) > k) pGetComp(q)--;
351    }
352  }
353  return result;
354}
355#endif
356
357void pDeleteComp(poly * p,int k)
358{
359  poly q;
360
361  while ((*p!=NULL) && (pGetComp(*p)==k)) pLmDelete(p);
362  if (*p==NULL) return;
363  q = *p;
364  if (pGetComp(q)>k)
365  {
366    pSubComp(q,1);
367    pSetmComp(q);
368  }
369  while (pNext(q)!=NULL)
370  {
371    if (pGetComp(pNext(q))==k)
372      pLmDelete(&(pNext(q)));
373    else
374    {
375      pIter(q);
376      if (pGetComp(q)>k)
377      {
378        pSubComp(q,1);
379        pSetmComp(q);
380      }
381    }
382  }
383}
384/*----------end of utilities for syzygies--------------*/
385
386/*2
387* divides p1 by its leading coefficient if it is a unit
388* (this will always be true over fields; but not over coefficient rings)
389*/
390void pNorm(poly p1)
391{
392#ifdef HAVE_RINGS
393  if (rField_is_Ring(currRing))
394  {
395    if (!nIsUnit(pGetCoeff(p1))) return;
396  }
397#endif
398  if (p1!=NULL)
399  {
400    if (pNext(p1)==NULL)
401    {
402      pSetCoeff(p1,nInit(1));
403      return;
404    }
405    poly h;
406    if (!nIsOne(pGetCoeff(p1)))
407    {
408      number k, c;
409      nNormalize(pGetCoeff(p1));
410      k = pGetCoeff(p1);
411      c = nInit(1);
412      pSetCoeff0(p1,c);
413      h = pNext(p1);
414      while (h!=NULL)
415      {
416        c=nDiv(pGetCoeff(h),k);
417        // no need to normalize: Z/p, R
418        // normalize already in nDiv: Q_a, Z/p_a
419        // remains: Q
420        if (rField_is_Q() && (!nIsOne(c))) nNormalize(c);
421        pSetCoeff(h,c);
422        pIter(h);
423      }
424      nDelete(&k);
425    }
426    else
427    {
428      if (nNormalize != nDummy2)
429      {
430        h = pNext(p1);
431        while (h!=NULL)
432        {
433          nNormalize(pGetCoeff(h));
434          pIter(h);
435        }
436      }
437    }
438  }
439}
440
441/*2
442*normalize all coefficients
443*/
444void p_Normalize(poly p,const ring r)
445{
446  if (rField_has_simple_inverse(r)) return; /* Z/p, GF(p,n), R, long R/C */
447  while (p!=NULL)
448  {
449#ifdef LDEBUG
450    if (currRing==r) {nTest(pGetCoeff(p));}
451#endif
452    n_Normalize(pGetCoeff(p),r);
453    pIter(p);
454  }
455}
456
457// splits p into polys with Exp(n) == 0 and Exp(n) != 0
458// Poly with Exp(n) != 0 is reversed
459static void pSplitAndReversePoly(poly p, int n, poly *non_zero, poly *zero)
460{
461  if (p == NULL)
462  {
463    *non_zero = NULL;
464    *zero = NULL;
465    return;
466  }
467  spolyrec sz;
468  poly z, n_z, next;
469  z = &sz;
470  n_z = NULL;
471
472  while(p != NULL)
473  {
474    next = pNext(p);
475    if (pGetExp(p, n) == 0)
476    {
477      pNext(z) = p;
478      pIter(z);
479    }
480    else
481    {
482      pNext(p) = n_z;
483      n_z = p;
484    }
485    p = next;
486  }
487  pNext(z) = NULL;
488  *zero = pNext(&sz);
489  *non_zero = n_z;
490  return;
491}
492
493/*3
494* substitute the n-th variable by 1 in p
495* destroy p
496*/
497static poly pSubst1 (poly p,int n)
498{
499  poly qq=NULL, result = NULL;
500  poly zero=NULL, non_zero=NULL;
501
502  // reverse, so that add is likely to be linear
503  pSplitAndReversePoly(p, n, &non_zero, &zero);
504
505  while (non_zero != NULL)
506  {
507    assume(pGetExp(non_zero, n) != 0);
508    qq = non_zero;
509    pIter(non_zero);
510    qq->next = NULL;
511    pSetExp(qq,n,0);
512    pSetm(qq);
513    result = pAdd(result,qq);
514  }
515  p = pAdd(result, zero);
516  pTest(p);
517  return p;
518}
519
520/*3
521* substitute the n-th variable by number e in p
522* destroy p
523*/
524static poly pSubst2 (poly p,int n, number e)
525{
526  assume( ! nIsZero(e) );
527  poly qq,result = NULL;
528  number nn, nm;
529  poly zero, non_zero;
530
531  // reverse, so that add is likely to be linear
532  pSplitAndReversePoly(p, n, &non_zero, &zero);
533
534  while (non_zero != NULL)
535  {
536    assume(pGetExp(non_zero, n) != 0);
537    qq = non_zero;
538    pIter(non_zero);
539    qq->next = NULL;
540    nPower(e, pGetExp(qq, n), &nn);
541    nm = nMult(nn, pGetCoeff(qq));
542#ifdef HAVE_RINGS
543    if (nIsZero(nm))
544    {
545      pLmFree(&qq);
546      nDelete(&nm);
547    }
548    else
549#endif
550    {
551      pSetCoeff(qq, nm);
552      pSetExp(qq, n, 0);
553      pSetm(qq);
554      result = pAdd(result,qq);
555    }
556    nDelete(&nn);
557  }
558  p = pAdd(result, zero);
559  pTest(p);
560  return p;
561}
562
563
564/* delete monoms whose n-th exponent is different from zero */
565poly pSubst0(poly p, int n)
566{
567  spolyrec res;
568  poly h = &res;
569  pNext(h) = p;
570
571  while (pNext(h)!=NULL)
572  {
573    if (pGetExp(pNext(h),n)!=0)
574    {
575      pLmDelete(&pNext(h));
576    }
577    else
578    {
579      pIter(h);
580    }
581  }
582  pTest(pNext(&res));
583  return pNext(&res);
584}
585
586/*2
587* substitute the n-th variable by e in p
588* destroy p
589*/
590poly pSubst(poly p, int n, poly e)
591{
592  if (e == NULL) return pSubst0(p, n);
593
594  if (pIsConstant(e))
595  {
596    if (nIsOne(pGetCoeff(e))) return pSubst1(p,n);
597    else return pSubst2(p, n, pGetCoeff(e));
598  }
599
600#ifdef HAVE_PLURAL
601  if (rIsPluralRing(currRing))
602  {
603    return nc_pSubst(p,n,e);
604  }
605#endif
606
607  int exponent,i;
608  poly h, res, m;
609  int *me,*ee;
610  number nu,nu1;
611
612  me=(int *)omAlloc((pVariables+1)*sizeof(int));
613  ee=(int *)omAlloc((pVariables+1)*sizeof(int));
614  if (e!=NULL) pGetExpV(e,ee);
615  res=NULL;
616  h=p;
617  while (h!=NULL)
618  {
619    if ((e!=NULL) || (pGetExp(h,n)==0))
620    {
621      m=pHead(h);
622      pGetExpV(m,me);
623      exponent=me[n];
624      me[n]=0;
625      for(i=pVariables;i>0;i--)
626        me[i]+=exponent*ee[i];
627      pSetExpV(m,me);
628      if (e!=NULL)
629      {
630        nPower(pGetCoeff(e),exponent,&nu);
631        nu1=nMult(pGetCoeff(m),nu);
632        nDelete(&nu);
633        pSetCoeff(m,nu1);
634      }
635      res=pAdd(res,m);
636    }
637    pLmDelete(&h);
638  }
639  omFreeSize((ADDRESS)me,(pVariables+1)*sizeof(int));
640  omFreeSize((ADDRESS)ee,(pVariables+1)*sizeof(int));
641  return res;
642}
643
644/* Returns TRUE if
645     * LM(p) | LM(lcm)
646     * LC(p) | LC(lcm) only if ring
647     * Exists i, j:
648         * LE(p, i)  != LE(lcm, i)
649         * LE(p1, i) != LE(lcm, i)   ==> LCM(p1, p) != lcm
650         * LE(p, j)  != LE(lcm, j)
651         * LE(p2, j) != LE(lcm, j)   ==> LCM(p2, p) != lcm
652*/
653BOOLEAN pCompareChain (poly p,poly p1,poly p2,poly lcm)
654{
655  int k, j;
656
657  if (lcm==NULL) return FALSE;
658
659  for (j=pVariables; j; j--)
660    if ( pGetExp(p,j) >  pGetExp(lcm,j)) return FALSE;
661  if ( pGetComp(p) !=  pGetComp(lcm)) return FALSE;
662  for (j=pVariables; j; j--)
663  {
664    if (pGetExp(p1,j)!=pGetExp(lcm,j))
665    {
666      if (pGetExp(p,j)!=pGetExp(lcm,j))
667      {
668        for (k=pVariables; k>j; k--)
669        {
670          if ((pGetExp(p,k)!=pGetExp(lcm,k))
671          && (pGetExp(p2,k)!=pGetExp(lcm,k)))
672            return TRUE;
673        }
674        for (k=j-1; k; k--)
675        {
676          if ((pGetExp(p,k)!=pGetExp(lcm,k))
677          && (pGetExp(p2,k)!=pGetExp(lcm,k)))
678            return TRUE;
679        }
680        return FALSE;
681      }
682    }
683    else if (pGetExp(p2,j)!=pGetExp(lcm,j))
684    {
685      if (pGetExp(p,j)!=pGetExp(lcm,j))
686      {
687        for (k=pVariables; k>j; k--)
688        {
689          if ((pGetExp(p,k)!=pGetExp(lcm,k))
690          && (pGetExp(p1,k)!=pGetExp(lcm,k)))
691            return TRUE;
692        }
693        for (k=j-1; k!=0 ; k--)
694        {
695          if ((pGetExp(p,k)!=pGetExp(lcm,k))
696          && (pGetExp(p1,k)!=pGetExp(lcm,k)))
697            return TRUE;
698        }
699        return FALSE;
700      }
701    }
702  }
703  return FALSE;
704}
705#ifdef HAVE_RATGRING
706BOOLEAN pCompareChainPart (poly p,poly p1,poly p2,poly lcm)
707{
708  int k, j;
709
710  if (lcm==NULL) return FALSE;
711
712  for (j=currRing->real_var_end; j>=currRing->real_var_start; j--)
713    if ( pGetExp(p,j) >  pGetExp(lcm,j)) return FALSE;
714  if ( pGetComp(p) !=  pGetComp(lcm)) return FALSE;
715  for (j=currRing->real_var_end; j>=currRing->real_var_start; j--)
716  {
717    if (pGetExp(p1,j)!=pGetExp(lcm,j))
718    {
719      if (pGetExp(p,j)!=pGetExp(lcm,j))
720      {
721        for (k=pVariables; k>j; k--)
722        for (k=currRing->real_var_end; k>j; k--)
723        {
724          if ((pGetExp(p,k)!=pGetExp(lcm,k))
725          && (pGetExp(p2,k)!=pGetExp(lcm,k)))
726            return TRUE;
727        }
728        for (k=j-1; k>=currRing->real_var_start; k--)
729        {
730          if ((pGetExp(p,k)!=pGetExp(lcm,k))
731          && (pGetExp(p2,k)!=pGetExp(lcm,k)))
732            return TRUE;
733        }
734        return FALSE;
735      }
736    }
737    else if (pGetExp(p2,j)!=pGetExp(lcm,j))
738    {
739      if (pGetExp(p,j)!=pGetExp(lcm,j))
740      {
741        for (k=currRing->real_var_end; k>j; k--)
742        {
743          if ((pGetExp(p,k)!=pGetExp(lcm,k))
744          && (pGetExp(p1,k)!=pGetExp(lcm,k)))
745            return TRUE;
746        }
747        for (k=j-1; k>=currRing->real_var_start; k--)
748        {
749          if ((pGetExp(p,k)!=pGetExp(lcm,k))
750          && (pGetExp(p1,k)!=pGetExp(lcm,k)))
751            return TRUE;
752        }
753        return FALSE;
754      }
755    }
756  }
757  return FALSE;
758}
759#endif
760
761int pSize(poly p)
762{
763  int count = 0;
764  while ( p != NULL )
765  {
766    count+= nSize( pGetCoeff( p ) );
767    pIter( p );
768  }
769  return count;
770}
771
772/*2
773* returns the length of a (numbers of monomials)
774* respect syzComp
775*/
776poly pLast(poly a, int &l)
777{
778  if (a == NULL)
779  {
780    l = 0;
781    return NULL;
782  }
783  l = 1;
784  if (! rIsSyzIndexRing(currRing))
785  {
786    while (pNext(a)!=NULL)
787    {
788      pIter(a);
789      l++;
790    }
791  }
792  else
793  {
794    int curr_limit = rGetCurrSyzLimit(currRing);
795    poly pp = a;
796    while ((a=pNext(a))!=NULL)
797    {
798      if (pGetComp(a)<=curr_limit/*syzComp*/)
799        l++;
800      else break;
801      pp = a;
802    }
803    a=pp;
804  }
805  return a;
806}
807
Note: See TracBrowser for help on using the repository browser.