source: git/polys/polys1.cc @ f34215

spielwiese
Last change on this file since f34215 was f34215, checked in by Hans Schoenemann <hannes@…>, 13 years ago
moved some ring-indep. stuff to p_polys
  • Property mode set to 100644
File size: 32.7 KB
Line 
1/****************************************
2*  Computer Algebra System SINGULAR     *
3****************************************/
4/* $Id$ */
5
6/*
7* ABSTRACT - all basic methods to manipulate polynomials:
8* independent of representation
9*/
10
11/* includes */
12#include <string.h>
13#include <kernel/mod2.h>
14#include <kernel/options.h>
15#include <kernel/numbers.h>
16#include <kernel/ffields.h>
17#include <omalloc/omalloc.h>
18#include <kernel/febase.h>
19#include <kernel/weight.h>
20#include <kernel/intvec.h>
21#include <kernel/longalg.h>
22#include <kernel/longtrans.h>
23#include <kernel/ring.h>
24#include <kernel/ideals.h>
25#include <kernel/polys.h>
26//#include "ipid.h"
27#ifdef HAVE_FACTORY
28#include <kernel/clapsing.h>
29#endif
30
31#ifdef HAVE_RATGRING
32#include <kernel/ratgring.h>
33#endif
34
35/*-------- several access procedures to monomials -------------------- */
36/*
37* the module weights for std
38*/
39static pFDegProc pOldFDeg;
40static pLDegProc pOldLDeg;
41static intvec * pModW;
42static BOOLEAN pOldLexOrder;
43
44static long pModDeg(poly p, ring r = currRing)
45{
46  long d=pOldFDeg(p, r);
47  int c=p_GetComp(p, r);
48  if ((c>0) && (pModW->range(c-1))) d+= (*pModW)[c-1];
49  return d;
50  //return pOldFDeg(p, r)+(*pModW)[p_GetComp(p, r)-1];
51}
52
53void pSetModDeg(intvec *w)
54{
55  if (w!=NULL)
56  {
57    pModW = w;
58    pOldFDeg = pFDeg;
59    pOldLDeg = pLDeg;
60    pOldLexOrder = pLexOrder;
61    pSetDegProcs(pModDeg);
62    pLexOrder = TRUE;
63  }
64  else
65  {
66    pModW = NULL;
67    pRestoreDegProcs(pOldFDeg, pOldLDeg);
68    pLexOrder = pOldLexOrder;
69  }
70}
71
72
73/*2
74* subtract p2 from p1, p1 and p2 are destroyed
75* do not put attention on speed: the procedure is only used in the interpreter
76*/
77poly pSub(poly p1, poly p2)
78{
79  return pAdd(p1, pNeg(p2));
80}
81
82/*3
83*  create binomial coef.
84*/
85static number* pnBin(int exp)
86{
87  int e, i, h;
88  number x, y, *bin=NULL;
89
90  x = nInit(exp);
91  if (nIsZero(x))
92  {
93    nDelete(&x);
94    return bin;
95  }
96  h = (exp >> 1) + 1;
97  bin = (number *)omAlloc0(h*sizeof(number));
98  bin[1] = x;
99  if (exp < 4)
100    return bin;
101  i = exp - 1;
102  for (e=2; e<h; e++)
103  {
104      x = nInit(i);
105      i--;
106      y = nMult(x,bin[e-1]);
107      nDelete(&x);
108      x = nInit(e);
109      bin[e] = nIntDiv(y,x);
110      nDelete(&x);
111      nDelete(&y);
112  }
113  return bin;
114}
115
116static void pnFreeBin(number *bin, int exp)
117{
118  int e, h = (exp >> 1) + 1;
119
120  if (bin[1] != NULL)
121  {
122    for (e=1; e<h; e++)
123      nDelete(&(bin[e]));
124  }
125  omFreeSize((ADDRESS)bin, h*sizeof(number));
126}
127
128/*3
129* compute for a monomial m
130* the power m^exp, exp > 1
131* destroys p
132*/
133static poly p_MonPower(poly p, int exp, const ring r)
134{
135  int i;
136
137  if(!n_IsOne(pGetCoeff(p),r))
138  {
139    number x, y;
140    y = pGetCoeff(p);
141    n_Power(y,exp,&x,r);
142    n_Delete(&y,r);
143    pSetCoeff0(p,x);
144  }
145  for (i=rVar(r); i!=0; i--)
146  {
147    p_MultExp(p,i, exp,r);
148  }
149  p_Setm(p,r);
150  return p;
151}
152
153/*3
154* compute for monomials p*q
155* destroys p, keeps q
156*/
157static void p_MonMult(poly p, poly q, const ring r)
158{
159  number x, y;
160
161  y = pGetCoeff(p);
162  x = n_Mult(y,pGetCoeff(q),r);
163  n_Delete(&y,r);
164  pSetCoeff0(p,x);
165  //for (int i=pVariables; i!=0; i--)
166  //{
167  //  pAddExp(p,i, pGetExp(q,i));
168  //}
169  //p->Order += q->Order;
170  p_ExpVectorAdd(p,q,r);
171}
172
173/*3
174* compute for monomials p*q
175* keeps p, q
176*/
177static poly p_MonMultC(poly p, poly q, const ring rr)
178{
179  number x;
180  poly r = p_Init(rr);
181
182  x = n_Mult(pGetCoeff(p),pGetCoeff(q),rr);
183  pSetCoeff0(r,x);
184  p_ExpVectorSum(r,p, q, rr);
185  return r;
186}
187
188/*
189*  compute for a poly p = head+tail, tail is monomial
190*          (head + tail)^exp, exp > 1
191*          with binomial coef.
192*/
193static poly p_TwoMonPower(poly p, int exp, const ring r)
194{
195  int eh, e;
196  long al;
197  poly *a;
198  poly tail, b, res, h;
199  number x;
200  number *bin = pnBin(exp);
201
202  tail = pNext(p);
203  if (bin == NULL)
204  {
205    p_MonPower(p,exp,r);
206    p_MonPower(tail,exp,r);
207#ifdef PDEBUG
208    p_Test(p,r);
209#endif
210    return p;
211  }
212  eh = exp >> 1;
213  al = (exp + 1) * sizeof(poly);
214  a = (poly *)omAlloc(al);
215  a[1] = p;
216  for (e=1; e<exp; e++)
217  {
218    a[e+1] = p_MonMultC(a[e],p,r);
219  }
220  res = a[exp];
221  b = p_Head(tail,r);
222  for (e=exp-1; e>eh; e--)
223  {
224    h = a[e];
225    x = n_Mult(bin[exp-e],pGetCoeff(h),r);
226    p_SetCoeff(h,x,r);
227    p_MonMult(h,b,r);
228    res = pNext(res) = h;
229    p_MonMult(b,tail,r);
230  }
231  for (e=eh; e!=0; e--)
232  {
233    h = a[e];
234    x = n_Mult(bin[e],pGetCoeff(h),r);
235    p_SetCoeff(h,x,r);
236    p_MonMult(h,b,r);
237    res = pNext(res) = h;
238    p_MonMult(b,tail,r);
239  }
240  p_LmDelete(&tail,r);
241  pNext(res) = b;
242  pNext(b) = NULL;
243  res = a[exp];
244  omFreeSize((ADDRESS)a, al);
245  pnFreeBin(bin, exp);
246//  tail=res;
247// while((tail!=NULL)&&(pNext(tail)!=NULL))
248// {
249//   if(nIsZero(pGetCoeff(pNext(tail))))
250//   {
251//     pLmDelete(&pNext(tail));
252//   }
253//   else
254//     pIter(tail);
255// }
256#ifdef PDEBUG
257  p_Test(res,r);
258#endif
259  return res;
260}
261
262static poly p_Pow(poly p, int i, const ring r)
263{
264  poly rc = p_Copy(p,r);
265  i -= 2;
266  do
267  {
268    rc = p_Mult_q(rc,p_Copy(p,r),r);
269    p_Normalize(rc,r);
270    i--;
271  }
272  while (i != 0);
273  return p_Mult_q(rc,p,r);
274}
275
276/*2
277* returns the i-th power of p
278* p will be destroyed
279*/
280poly p_Power(poly p, int i, const ring r)
281{
282  poly rc=NULL;
283
284  if (i==0)
285  {
286    p_Delete(&p,r);
287    return p_One(r);
288  }
289
290  if(p!=NULL)
291  {
292    if ( (i > 0) && ((unsigned long ) i > (r->bitmask)))
293    {
294      Werror("exponent %d is too large, max. is %ld",i,r->bitmask);
295      return NULL;
296    }
297    switch (i)
298    {
299// cannot happen, see above
300//      case 0:
301//      {
302//        rc=pOne();
303//        pDelete(&p);
304//        break;
305//      }
306      case 1:
307        rc=p;
308        break;
309      case 2:
310        rc=p_Mult_q(p_Copy(p,r),p,r);
311        break;
312      default:
313        if (i < 0)
314        {
315          p_Delete(&p,r);
316          return NULL;
317        }
318        else
319        {
320#ifdef HAVE_PLURAL
321          if (rIsPluralRing(r)) /* in the NC case nothing helps :-( */
322          {
323            int j=i;
324            rc = p_Copy(p,r);
325            while (j>1)
326            {
327              rc = p_Mult_q(p_Copy(p,r),rc,r);
328              j--;
329            }
330            p_Delete(&p,r);
331            return rc;
332          }
333#endif
334          rc = pNext(p);
335          if (rc == NULL)
336            return p_MonPower(p,i,r);
337          /* else: binom ?*/
338          int char_p=rChar(r);
339          if ((pNext(rc) != NULL)
340#ifdef HAVE_RINGS
341             || rField_is_Ring(r)
342#endif
343             )
344            return p_Pow(p,i,r);
345          if ((char_p==0) || (i<=char_p))
346            return p_TwoMonPower(p,i,r);
347          poly p_p=p_TwoMonPower(p_Copy(p,r),char_p,r);
348          return p_Mult_q(p_Power(p,i-char_p,r),p_p,r);
349        }
350      /*end default:*/
351    }
352  }
353  return rc;
354}
355
356/*2
357* returns the partial differentiate of a by the k-th variable
358* does not destroy the input
359*/
360poly pDiff(poly a, int k)
361{
362  poly res, f, last;
363  number t;
364
365  last = res = NULL;
366  while (a!=NULL)
367  {
368    if (pGetExp(a,k)!=0)
369    {
370      f = pLmInit(a);
371      t = nInit(pGetExp(a,k));
372      pSetCoeff0(f,nMult(t,pGetCoeff(a)));
373      nDelete(&t);
374      if (nIsZero(pGetCoeff(f)))
375        pLmDelete(&f);
376      else
377      {
378        pDecrExp(f,k);
379        pSetm(f);
380        if (res==NULL)
381        {
382          res=last=f;
383        }
384        else
385        {
386          pNext(last)=f;
387          last=f;
388        }
389      }
390    }
391    pIter(a);
392  }
393  return res;
394}
395
396static poly pDiffOpM(poly a, poly b,BOOLEAN multiply)
397{
398  int i,j,s;
399  number n,h,hh;
400  poly p=pOne();
401  n=nMult(pGetCoeff(a),pGetCoeff(b));
402  for(i=pVariables;i>0;i--)
403  {
404    s=pGetExp(b,i);
405    if (s<pGetExp(a,i))
406    {
407      nDelete(&n);
408      pLmDelete(&p);
409      return NULL;
410    }
411    if (multiply)
412    {
413      for(j=pGetExp(a,i); j>0;j--)
414      {
415        h = nInit(s);
416        hh=nMult(n,h);
417        nDelete(&h);
418        nDelete(&n);
419        n=hh;
420        s--;
421      }
422      pSetExp(p,i,s);
423    }
424    else
425    {
426      pSetExp(p,i,s-pGetExp(a,i));
427    }
428  }
429  pSetm(p);
430  /*if (multiply)*/ pSetCoeff(p,n);
431  if (nIsZero(n))  p=pLmDeleteAndNext(p); // return NULL as p is a monomial
432  return p;
433}
434
435poly pDiffOp(poly a, poly b,BOOLEAN multiply)
436{
437  poly result=NULL;
438  poly h;
439  for(;a!=NULL;pIter(a))
440  {
441    for(h=b;h!=NULL;pIter(h))
442    {
443      result=pAdd(result,pDiffOpM(a,h,multiply));
444    }
445  }
446  return result;
447}
448
449int pMaxCompProc(poly p)
450{
451  return pMaxComp(p);
452}
453
454/*2
455* handle memory request for sets of polynomials (ideals)
456* l is the length of *p, increment is the difference (may be negative)
457*/
458void pEnlargeSet(polyset *p, int l, int increment)
459{
460  polyset h;
461
462  h=(polyset)omReallocSize((poly*)*p,l*sizeof(poly),(l+increment)*sizeof(poly));
463  if (increment>0)
464  {
465    //for (i=l; i<l+increment; i++)
466    //  h[i]=NULL;
467    memset(&(h[l]),0,increment*sizeof(poly));
468  }
469  *p=h;
470}
471
472number pInitContent(poly ph);
473number pInitContent_a(poly ph);
474
475void p_Content(poly ph, const ring r)
476{
477#ifdef HAVE_RINGS
478  if (rField_is_Ring(r))
479  {
480    if (ph!=NULL)
481    {
482      number k = nGetUnit(pGetCoeff(ph));
483      if (!nGreaterZero(pGetCoeff(ph))) k = nNeg(k); // in-place negation
484      if (!nIsOne(k))
485      {
486        number tmpNumber = k;
487        k = nInvers(k);
488        nDelete(&tmpNumber);
489        poly h = pNext(ph);
490        p_Mult_nn(ph,k,currRing);
491        pNormalize(ph);
492      }
493      nDelete(&k);
494    }
495    return;
496  }
497#endif
498  number h,d;
499  poly p;
500
501  //  if(TEST_OPT_CONTENTSB) return;
502  if(pNext(ph)==NULL)
503  {
504    pSetCoeff(ph,nInit(1));
505  }
506  else
507  {
508    nNormalize(pGetCoeff(ph));
509    if(!nGreaterZero(pGetCoeff(ph))) ph = pNeg(ph);
510    if (rField_is_Q())
511    {
512      h=pInitContent(ph);
513      p=ph;
514    }
515    else if ((rField_is_Extension(r))
516    && ((rPar(r)>1)||(r->minpoly==NULL)))
517    {
518      h=pInitContent_a(ph);
519      p=ph;
520    }
521    else
522    {
523      h=nCopy(pGetCoeff(ph));
524      p = pNext(ph);
525    }
526    while (p!=NULL)
527    {
528      nNormalize(pGetCoeff(p));
529      d=nGcd(h,pGetCoeff(p),r);
530      nDelete(&h);
531      h = d;
532      if(nIsOne(h))
533      {
534        break;
535      }
536      pIter(p);
537    }
538    p = ph;
539    //number tmp;
540    if(!nIsOne(h))
541    {
542      while (p!=NULL)
543      {
544        //d = nDiv(pGetCoeff(p),h);
545        //tmp = nIntDiv(pGetCoeff(p),h);
546        //if (!nEqual(d,tmp))
547        //{
548        //  StringSetS("** div0:");nWrite(pGetCoeff(p));StringAppendS("/");
549        //  nWrite(h);StringAppendS("=");nWrite(d);StringAppendS(" int:");
550        //  nWrite(tmp);Print(StringAppendS("\n"));
551        //}
552        //nDelete(&tmp);
553        if (rField_is_Zp_a(currRing) || rField_is_Q_a(currRing))
554          d = nDiv(pGetCoeff(p),h);
555        else
556          d = nIntDiv(pGetCoeff(p),h);
557        pSetCoeff(p,d);
558        pIter(p);
559      }
560    }
561    nDelete(&h);
562#ifdef HAVE_FACTORY
563    if ( (nGetChar() == 1) || (nGetChar() < 0) ) /* Q[a],Q(a),Zp[a],Z/p(a) */
564    {
565      singclap_divide_content(ph);
566      if(!nGreaterZero(pGetCoeff(ph))) ph = pNeg(ph);
567    }
568#endif
569    if (rField_is_Q_a(r))
570    {
571      number hzz = nlInit(1, r);
572      h = nlInit(1, r);
573      p=ph;
574      while (p!=NULL)
575      { // each monom: coeff in Q_a
576        lnumber c_n_n=(lnumber)pGetCoeff(p);
577        napoly c_n=c_n_n->z;
578        while (c_n!=NULL)
579        { // each monom: coeff in Q
580          d=nlLcm(hzz,pGetCoeff(c_n),r->algring);
581          n_Delete(&hzz,r->algring);
582          hzz=d;
583          pIter(c_n);
584        }
585        c_n=c_n_n->n;
586        while (c_n!=NULL)
587        { // each monom: coeff in Q
588          d=nlLcm(h,pGetCoeff(c_n),r->algring);
589          n_Delete(&h,r->algring);
590          h=d;
591          pIter(c_n);
592        }
593        pIter(p);
594      }
595      /* hzz contains the 1/lcm of all denominators in c_n_n->z*/
596      /* h contains the 1/lcm of all denominators in c_n_n->n*/
597      number htmp=nlInvers(h);
598      number hzztmp=nlInvers(hzz);
599      number hh=nlMult(hzz,h);
600      nlDelete(&hzz,r->algring);
601      nlDelete(&h,r->algring);
602      number hg=nlGcd(hzztmp,htmp,r->algring);
603      nlDelete(&hzztmp,r->algring);
604      nlDelete(&htmp,r->algring);
605      h=nlMult(hh,hg);
606      nlDelete(&hg,r->algring);
607      nlDelete(&hh,r->algring);
608      nlNormalize(h);
609      if(!nlIsOne(h))
610      {
611        p=ph;
612        while (p!=NULL)
613        { // each monom: coeff in Q_a
614          lnumber c_n_n=(lnumber)pGetCoeff(p);
615          napoly c_n=c_n_n->z;
616          while (c_n!=NULL)
617          { // each monom: coeff in Q
618            d=nlMult(h,pGetCoeff(c_n));
619            nlNormalize(d);
620            nlDelete(&pGetCoeff(c_n),r->algring);
621            pGetCoeff(c_n)=d;
622            pIter(c_n);
623          }
624          c_n=c_n_n->n;
625          while (c_n!=NULL)
626          { // each monom: coeff in Q
627            d=nlMult(h,pGetCoeff(c_n));
628            nlNormalize(d);
629            nlDelete(&pGetCoeff(c_n),r->algring);
630            pGetCoeff(c_n)=d;
631            pIter(c_n);
632          }
633          pIter(p);
634        }
635      }
636      nlDelete(&h,r->algring);
637    }
638  }
639}
640
641void pSimpleContent(poly ph,int smax)
642{
643  //if(TEST_OPT_CONTENTSB) return;
644  if (ph==NULL) return;
645  if (pNext(ph)==NULL)
646  {
647    pSetCoeff(ph,nInit(1));
648    return;
649  }
650  if ((pNext(pNext(ph))==NULL)||(!rField_is_Q()))
651  {
652    return;
653  }
654  number d=pInitContent(ph);
655  if (nlSize(d)<=smax)
656  {
657    //if (TEST_OPT_PROT) PrintS("G");
658    return;
659  }
660  poly p=ph;
661  number h=d;
662  if (smax==1) smax=2;
663  while (p!=NULL)
664  {
665#if 0
666    d=nlGcd(h,pGetCoeff(p),currRing);
667    nlDelete(&h,currRing);
668    h = d;
669#else
670    nlInpGcd(h,pGetCoeff(p),currRing);
671#endif
672    if(nlSize(h)<smax)
673    {
674      //if (TEST_OPT_PROT) PrintS("g");
675      return;
676    }
677    pIter(p);
678  }
679  p = ph;
680  if (!nlGreaterZero(pGetCoeff(p))) h=nlNeg(h);
681  if(nlIsOne(h)) return;
682  //if (TEST_OPT_PROT) PrintS("c");
683  //
684  number inv=nlInvers(h);
685  p_Mult_nn(p,inv,currRing);
686  pNormalize(p);
687  //while (p!=NULL)
688  //{
689#if 1
690  //  d = nlIntDiv(pGetCoeff(p),h);
691  //  pSetCoeff(p,d);
692#else
693  //  nlInpIntDiv(pGetCoeff(p),h,currRing);
694#endif
695  //  pIter(p);
696  //}
697  nlDelete(&inv,currRing);
698  nlDelete(&h,currRing);
699}
700
701number pInitContent(poly ph)
702// only for coefficients in Q
703#if 0
704{
705  //assume(!TEST_OPT_CONTENTSB);
706  assume(ph!=NULL);
707  assume(pNext(ph)!=NULL);
708  assume(rField_is_Q());
709  if (pNext(pNext(ph))==NULL)
710  {
711    return nlGetNom(pGetCoeff(pNext(ph)),currRing);
712  }
713  poly p=ph;
714  number n1=nlGetNom(pGetCoeff(p),currRing);
715  pIter(p);
716  number n2=nlGetNom(pGetCoeff(p),currRing);
717  pIter(p);
718  number d;
719  number t;
720  loop
721  {
722    nlNormalize(pGetCoeff(p));
723    t=nlGetNom(pGetCoeff(p),currRing);
724    if (nlGreaterZero(t))
725      d=nlAdd(n1,t);
726    else
727      d=nlSub(n1,t);
728    nlDelete(&t,currRing);
729    nlDelete(&n1,currRing);
730    n1=d;
731    pIter(p);
732    if (p==NULL) break;
733    nlNormalize(pGetCoeff(p));
734    t=nlGetNom(pGetCoeff(p),currRing);
735    if (nlGreaterZero(t))
736      d=nlAdd(n2,t);
737    else
738      d=nlSub(n2,t);
739    nlDelete(&t,currRing);
740    nlDelete(&n2,currRing);
741    n2=d;
742    pIter(p);
743    if (p==NULL) break;
744  }
745  d=nlGcd(n1,n2,currRing);
746  nlDelete(&n1,currRing);
747  nlDelete(&n2,currRing);
748  return d;
749}
750#else
751{
752  number d=pGetCoeff(ph);
753  if(SR_HDL(d)&SR_INT) return d;
754  int s=mpz_size1(d->z);
755  int s2=-1;
756  number d2;
757  loop
758  {
759    pIter(ph);
760    if(ph==NULL)
761    {
762      if (s2==-1) return nlCopy(d);
763      break;
764    }
765    if (SR_HDL(pGetCoeff(ph))&SR_INT)
766    {
767      s2=s;
768      d2=d;
769      s=0;
770      d=pGetCoeff(ph);
771      if (s2==0) break;
772    }
773    else
774    if (mpz_size1((pGetCoeff(ph)->z))<=s)
775    {
776      s2=s;
777      d2=d;
778      d=pGetCoeff(ph);
779      s=mpz_size1(d->z);
780    }
781  }
782  return nlGcd(d,d2,currRing);
783}
784#endif
785
786number pInitContent_a(poly ph)
787// only for coefficients in K(a) anf K(a,...)
788{
789  number d=pGetCoeff(ph);
790  int s=naParDeg(d);
791  if (s /* naParDeg(d)*/ <=1) return naCopy(d);
792  int s2=-1;
793  number d2;
794  int ss;
795  loop
796  {
797    pIter(ph);
798    if(ph==NULL)
799    {
800      if (s2==-1) return naCopy(d);
801      break;
802    }
803    if ((ss=naParDeg(pGetCoeff(ph)))<s)
804    {
805      s2=s;
806      d2=d;
807      s=ss;
808      d=pGetCoeff(ph);
809      if (s2<=1) break;
810    }
811  }
812  return naGcd(d,d2,currRing);
813}
814
815
816//void pContent(poly ph)
817//{
818//  number h,d;
819//  poly p;
820//
821//  p = ph;
822//  if(pNext(p)==NULL)
823//  {
824//    pSetCoeff(p,nInit(1));
825//  }
826//  else
827//  {
828//#ifdef PDEBUG
829//    if (!pTest(p)) return;
830//#endif
831//    nNormalize(pGetCoeff(p));
832//    if(!nGreaterZero(pGetCoeff(ph)))
833//    {
834//      ph = pNeg(ph);
835//      nNormalize(pGetCoeff(p));
836//    }
837//    h=pGetCoeff(p);
838//    pIter(p);
839//    while (p!=NULL)
840//    {
841//      nNormalize(pGetCoeff(p));
842//      if (nGreater(h,pGetCoeff(p))) h=pGetCoeff(p);
843//      pIter(p);
844//    }
845//    h=nCopy(h);
846//    p=ph;
847//    while (p!=NULL)
848//    {
849//      d=nGcd(h,pGetCoeff(p));
850//      nDelete(&h);
851//      h = d;
852//      if(nIsOne(h))
853//      {
854//        break;
855//      }
856//      pIter(p);
857//    }
858//    p = ph;
859//    //number tmp;
860//    if(!nIsOne(h))
861//    {
862//      while (p!=NULL)
863//      {
864//        d = nIntDiv(pGetCoeff(p),h);
865//        pSetCoeff(p,d);
866//        pIter(p);
867//      }
868//    }
869//    nDelete(&h);
870//#ifdef HAVE_FACTORY
871//    if ( (nGetChar() == 1) || (nGetChar() < 0) ) /* Q[a],Q(a),Zp[a],Z/p(a) */
872//    {
873//      pTest(ph);
874//      singclap_divide_content(ph);
875//      pTest(ph);
876//    }
877//#endif
878//  }
879//}
880#if 0
881void p_Content(poly ph, ring r)
882{
883  number h,d;
884  poly p;
885
886  if(pNext(ph)==NULL)
887  {
888    pSetCoeff(ph,n_Init(1,r));
889  }
890  else
891  {
892    n_Normalize(pGetCoeff(ph),r);
893    if(!n_GreaterZero(pGetCoeff(ph),r)) ph = p_Neg(ph,r);
894    h=n_Copy(pGetCoeff(ph),r);
895    p = pNext(ph);
896    while (p!=NULL)
897    {
898      n_Normalize(pGetCoeff(p),r);
899      d=n_Gcd(h,pGetCoeff(p),r);
900      n_Delete(&h,r);
901      h = d;
902      if(n_IsOne(h,r))
903      {
904        break;
905      }
906      pIter(p);
907    }
908    p = ph;
909    //number tmp;
910    if(!n_IsOne(h,r))
911    {
912      while (p!=NULL)
913      {
914        //d = nDiv(pGetCoeff(p),h);
915        //tmp = nIntDiv(pGetCoeff(p),h);
916        //if (!nEqual(d,tmp))
917        //{
918        //  StringSetS("** div0:");nWrite(pGetCoeff(p));StringAppendS("/");
919        //  nWrite(h);StringAppendS("=");nWrite(d);StringAppendS(" int:");
920        //  nWrite(tmp);Print(StringAppendS("\n"));
921        //}
922        //nDelete(&tmp);
923        d = n_IntDiv(pGetCoeff(p),h,r);
924        p_SetCoeff(p,d,r);
925        pIter(p);
926      }
927    }
928    n_Delete(&h,r);
929#ifdef HAVE_FACTORY
930    //if ( (n_GetChar(r) == 1) || (n_GetChar(r) < 0) ) /* Q[a],Q(a),Zp[a],Z/p(a) */
931    //{
932    //  singclap_divide_content(ph);
933    //  if(!n_GreaterZero(pGetCoeff(ph),r)) ph = p_Neg(ph,r);
934    //}
935#endif
936  }
937}
938#endif
939
940poly p_Cleardenom(poly ph, const ring r)
941{
942  poly start=ph;
943  number d, h;
944  poly p;
945
946#ifdef HAVE_RINGS
947  if (rField_is_Ring(r))
948  {
949    p_Content(ph,r);
950    return start;
951  }
952#endif
953  if (rField_is_Zp(r) && TEST_OPT_INTSTRATEGY) return start;
954  p = ph;
955  if(pNext(p)==NULL)
956  {
957    /*
958    if (TEST_OPT_CONTENTSB)
959    {
960      number n=nGetDenom(pGetCoeff(p));
961      if (!nIsOne(n))
962      {
963        number nn=nMult(pGetCoeff(p),n);
964        nNormalize(nn);
965        pSetCoeff(p,nn);
966      }
967      nDelete(&n);
968    }
969    else
970    */
971      pSetCoeff(p,nInit(1));
972  }
973  else
974  {
975    h = nInit(1);
976    while (p!=NULL)
977    {
978      nNormalize(pGetCoeff(p));
979      d=nLcm(h,pGetCoeff(p),currRing);
980      nDelete(&h);
981      h=d;
982      pIter(p);
983    }
984    /* contains the 1/lcm of all denominators */
985    if(!nIsOne(h))
986    {
987      p = ph;
988      while (p!=NULL)
989      {
990        /* should be:
991        * number hh;
992        * nGetDenom(p->coef,&hh);
993        * nMult(&h,&hh,&d);
994        * nNormalize(d);
995        * nDelete(&hh);
996        * nMult(d,p->coef,&hh);
997        * nDelete(&d);
998        * nDelete(&(p->coef));
999        * p->coef =hh;
1000        */
1001        d=nMult(h,pGetCoeff(p));
1002        nNormalize(d);
1003        pSetCoeff(p,d);
1004        pIter(p);
1005      }
1006      nDelete(&h);
1007      if (nGetChar()==1)
1008      {
1009        loop
1010        {
1011          h = nInit(1);
1012          p=ph;
1013          while (p!=NULL)
1014          {
1015            d=nLcm(h,pGetCoeff(p),currRing);
1016            nDelete(&h);
1017            h=d;
1018            pIter(p);
1019          }
1020          /* contains the 1/lcm of all denominators */
1021          if(!nIsOne(h))
1022          {
1023            p = ph;
1024            while (p!=NULL)
1025            {
1026              /* should be:
1027              * number hh;
1028              * nGetDenom(p->coef,&hh);
1029              * nMult(&h,&hh,&d);
1030              * nNormalize(d);
1031              * nDelete(&hh);
1032              * nMult(d,p->coef,&hh);
1033              * nDelete(&d);
1034              * nDelete(&(p->coef));
1035              * p->coef =hh;
1036              */
1037              d=nMult(h,pGetCoeff(p));
1038              nNormalize(d);
1039              pSetCoeff(p,d);
1040              pIter(p);
1041            }
1042            nDelete(&h);
1043          }
1044          else
1045          {
1046            nDelete(&h);
1047            break;
1048          }
1049        }
1050      }
1051    }
1052    if (h!=NULL) nDelete(&h);
1053 
1054    p_Content(ph,r);
1055#ifdef HAVE_RATGRING
1056    if (rIsRatGRing(r))
1057    {
1058      /* quick unit detection in the rational case is done in gr_nc_bba */
1059      pContentRat(ph);
1060      start=ph;
1061    }
1062#endif
1063  }
1064  return start;
1065}
1066
1067void p_Cleardenom_n(poly ph,const ring r,number &c)
1068{
1069  number d, h;
1070  poly p;
1071
1072  p = ph;
1073  if(pNext(p)==NULL)
1074  {
1075    c=nInvers(pGetCoeff(p));
1076    pSetCoeff(p,nInit(1));
1077  }
1078  else
1079  {
1080    h = nInit(1);
1081    while (p!=NULL)
1082    {
1083      nNormalize(pGetCoeff(p));
1084      d=nLcm(h,pGetCoeff(p),r);
1085      nDelete(&h);
1086      h=d;
1087      pIter(p);
1088    }
1089    c=h;
1090    /* contains the 1/lcm of all denominators */
1091    if(!nIsOne(h))
1092    {
1093      p = ph;
1094      while (p!=NULL)
1095      {
1096        /* should be:
1097        * number hh;
1098        * nGetDenom(p->coef,&hh);
1099        * nMult(&h,&hh,&d);
1100        * nNormalize(d);
1101        * nDelete(&hh);
1102        * nMult(d,p->coef,&hh);
1103        * nDelete(&d);
1104        * nDelete(&(p->coef));
1105        * p->coef =hh;
1106        */
1107        d=nMult(h,pGetCoeff(p));
1108        nNormalize(d);
1109        pSetCoeff(p,d);
1110        pIter(p);
1111      }
1112      if (nGetChar()==1)
1113      {
1114        loop
1115        {
1116          h = nInit(1);
1117          p=ph;
1118          while (p!=NULL)
1119          {
1120            d=nLcm(h,pGetCoeff(p),r);
1121            nDelete(&h);
1122            h=d;
1123            pIter(p);
1124          }
1125          /* contains the 1/lcm of all denominators */
1126          if(!nIsOne(h))
1127          {
1128            p = ph;
1129            while (p!=NULL)
1130            {
1131              /* should be:
1132              * number hh;
1133              * nGetDenom(p->coef,&hh);
1134              * nMult(&h,&hh,&d);
1135              * nNormalize(d);
1136              * nDelete(&hh);
1137              * nMult(d,p->coef,&hh);
1138              * nDelete(&d);
1139              * nDelete(&(p->coef));
1140              * p->coef =hh;
1141              */
1142              d=nMult(h,pGetCoeff(p));
1143              nNormalize(d);
1144              pSetCoeff(p,d);
1145              pIter(p);
1146            }
1147            number t=nMult(c,h);
1148            nDelete(&c);
1149            c=t;
1150          }
1151          else
1152          {
1153            break;
1154          }
1155          nDelete(&h);
1156        }
1157      }
1158    }
1159  }
1160}
1161
1162number p_GetAllDenom(poly ph, const ring r)
1163{
1164  number d=n_Init(1,r);
1165  poly p = ph;
1166
1167  while (p!=NULL)
1168  {
1169    number h=n_GetDenom(pGetCoeff(p),r);
1170    if (!n_IsOne(h,r))
1171    {
1172      number dd=n_Mult(d,h,r);
1173      n_Delete(&d,r);
1174      d=dd;
1175    }
1176    n_Delete(&h,r);
1177    pIter(p);
1178  }
1179  return d;
1180}
1181
1182/*2
1183*tests if p is homogeneous with respect to the actual weigths
1184*/
1185BOOLEAN pIsHomogeneous (poly p)
1186{
1187  poly qp=p;
1188  int o;
1189
1190  if ((p == NULL) || (pNext(p) == NULL)) return TRUE;
1191  pFDegProc d;
1192  if (pLexOrder && (currRing->order[0]==ringorder_lp))
1193    d=p_Totaldegree;
1194  else 
1195    d=pFDeg;
1196  o = d(p,currRing);
1197  do
1198  {
1199    if (d(qp,currRing) != o) return FALSE;
1200    pIter(qp);
1201  }
1202  while (qp != NULL);
1203  return TRUE;
1204}
1205
1206/*2
1207*returns a re-ordered copy of a polynomial, with permutation of the variables
1208*/
1209poly pPermPoly (poly p, int * perm, const ring oldRing, nMapFunc nMap,
1210   int *par_perm, int OldPar)
1211{
1212  int OldpVariables = oldRing->N;
1213  poly result = NULL;
1214  poly result_last = NULL;
1215  poly aq=NULL; /* the map coefficient */
1216  poly qq; /* the mapped monomial */
1217
1218  while (p != NULL)
1219  {
1220    if ((OldPar==0)||(rField_is_GF(oldRing)))
1221    {
1222      qq = pInit();
1223      number n=nMap(pGetCoeff(p));
1224      if ((currRing->minpoly!=NULL)
1225      && ((rField_is_Zp_a()) || (rField_is_Q_a())))
1226      {
1227        nNormalize(n);
1228      }
1229      pGetCoeff(qq)=n;
1230    // coef may be zero:  pTest(qq);
1231    }
1232    else
1233    {
1234      qq=pOne();
1235      aq=napPermNumber(pGetCoeff(p),par_perm,OldPar, oldRing);
1236      if ((aq!=NULL) && (currRing->minpoly!=NULL)
1237      && ((rField_is_Zp_a()) || (rField_is_Q_a())))
1238      {
1239        pNormalize(aq);
1240      }
1241      pTest(aq);
1242      if (aq==NULL)
1243        pSetCoeff(qq,nInit(0));
1244    }
1245    if (rRing_has_Comp(currRing)) pSetComp(qq, p_GetComp(p,oldRing));
1246    if (nIsZero(pGetCoeff(qq)))
1247    {
1248      pLmDelete(&qq);
1249    }
1250    else
1251    {
1252      int i;
1253      int mapped_to_par=0;
1254      for(i=1; i<=OldpVariables; i++)
1255      {
1256        int e=p_GetExp(p,i,oldRing);
1257        if (e!=0)
1258        {
1259          if (perm==NULL)
1260          {
1261            pSetExp(qq,i, e);
1262          }
1263          else if (perm[i]>0)
1264            pAddExp(qq,perm[i], e/*p_GetExp( p,i,oldRing)*/);
1265          else if (perm[i]<0)
1266          {
1267            if (rField_is_GF())
1268            {
1269              number c=pGetCoeff(qq);
1270              number ee=nfPar(1);
1271              number eee;nfPower(ee,e,&eee); //nfDelete(ee,currRing);
1272              ee=nfMult(c,eee);
1273              //nfDelete(c,currRing);nfDelete(eee,currRing);
1274              pSetCoeff0(qq,ee);
1275            }
1276            else
1277            {
1278              lnumber c=(lnumber)pGetCoeff(qq);
1279              if (c->z->next==NULL)
1280                napAddExp(c->z,-perm[i],e/*p_GetExp( p,i,oldRing)*/);
1281              else /* more difficult: we have really to multiply: */
1282              {
1283                lnumber mmc=(lnumber)naInit(1,currRing);
1284                napSetExp(mmc->z,-perm[i],e/*p_GetExp( p,i,oldRing)*/);
1285                napSetm(mmc->z);
1286                pGetCoeff(qq)=naMult((number)c,(number)mmc);
1287                nDelete((number *)&c);
1288                nDelete((number *)&mmc); 
1289              }
1290              mapped_to_par=1;
1291            }
1292          }
1293          else
1294          {
1295            /* this variable maps to 0 !*/
1296            pLmDelete(&qq);
1297            break;
1298          }
1299        }
1300      }
1301      if (mapped_to_par
1302      && (currRing->minpoly!=NULL))
1303      {
1304        number n=pGetCoeff(qq);
1305        nNormalize(n);
1306        pGetCoeff(qq)=n;
1307      }
1308    }
1309    pIter(p);
1310#if 1
1311    if (qq!=NULL)
1312    {
1313      pSetm(qq);
1314      pTest(aq);
1315      pTest(qq);
1316      if (aq!=NULL) qq=pMult(aq,qq);
1317      aq = qq;
1318      while (pNext(aq) != NULL) pIter(aq);
1319      if (result_last==NULL)
1320      {
1321        result=qq;
1322      }
1323      else
1324      {
1325        pNext(result_last)=qq;
1326      }
1327      result_last=aq;
1328      aq = NULL;
1329    }
1330    else if (aq!=NULL)
1331    {
1332      pDelete(&aq);
1333    }
1334  }
1335  result=pSortAdd(result);
1336#else
1337  //  if (qq!=NULL)
1338  //  {
1339  //    pSetm(qq);
1340  //    pTest(qq);
1341  //    pTest(aq);
1342  //    if (aq!=NULL) qq=pMult(aq,qq);
1343  //    aq = qq;
1344  //    while (pNext(aq) != NULL) pIter(aq);
1345  //    pNext(aq) = result;
1346  //    aq = NULL;
1347  //    result = qq;
1348  //  }
1349  //  else if (aq!=NULL)
1350  //  {
1351  //    pDelete(&aq);
1352  //  }
1353  //}
1354  //p = result;
1355  //result = NULL;
1356  //while (p != NULL)
1357  //{
1358  //  qq = p;
1359  //  pIter(p);
1360  //  qq->next = NULL;
1361  //  result = pAdd(result, qq);
1362  //}
1363#endif
1364  pTest(result);
1365  return result;
1366}
1367
1368poly ppJet(poly p, int m)
1369{
1370  poly r=NULL;
1371  poly t=NULL;
1372
1373  while (p!=NULL)
1374  {
1375    if (p_Totaldegree(p,currRing)<=m)
1376    {
1377      if (r==NULL)
1378        r=pHead(p);
1379      else
1380      if (t==NULL)
1381      {
1382        pNext(r)=pHead(p);
1383        t=pNext(r);
1384      }
1385      else
1386      {
1387        pNext(t)=pHead(p);
1388        pIter(t);
1389      }
1390    }
1391    pIter(p);
1392  }
1393  return r;
1394}
1395
1396poly pJet(poly p, int m)
1397{
1398  poly t=NULL;
1399
1400  while((p!=NULL) && (p_Totaldegree(p,currRing)>m)) pLmDelete(&p);
1401  if (p==NULL) return NULL;
1402  poly r=p;
1403  while (pNext(p)!=NULL)
1404  {
1405    if (p_Totaldegree(pNext(p),currRing)>m)
1406    {
1407      pLmDelete(&pNext(p));
1408    }
1409    else
1410      pIter(p);
1411  }
1412  return r;
1413}
1414
1415poly ppJetW(poly p, int m, short *w)
1416{
1417  poly r=NULL;
1418  poly t=NULL;
1419  while (p!=NULL)
1420  {
1421    if (totaldegreeWecart_IV(p,currRing,w)<=m)
1422    {
1423      if (r==NULL)
1424        r=pHead(p);
1425      else
1426      if (t==NULL)
1427      {
1428        pNext(r)=pHead(p);
1429        t=pNext(r);
1430      }
1431      else
1432      {
1433        pNext(t)=pHead(p);
1434        pIter(t);
1435      }
1436    }
1437    pIter(p);
1438  }
1439  return r;
1440}
1441
1442poly pJetW(poly p, int m, short *w)
1443{
1444  while((p!=NULL) && (totaldegreeWecart_IV(p,currRing,w)>m)) pLmDelete(&p);
1445  if (p==NULL) return NULL;
1446  poly r=p;
1447  while (pNext(p)!=NULL)
1448  {
1449    if (totaldegreeWecart_IV(pNext(p),currRing,w)>m)
1450    {
1451      pLmDelete(&pNext(p));
1452    }
1453    else
1454      pIter(p);
1455  }
1456  return r;
1457}
1458
1459int pMinDeg(poly p,intvec *w)
1460{
1461  if(p==NULL)
1462    return -1;
1463  int d=-1;
1464  while(p!=NULL)
1465  {
1466    int d0=0;
1467    for(int j=0;j<pVariables;j++)
1468      if(w==NULL||j>=w->length())
1469        d0+=pGetExp(p,j+1);
1470      else
1471        d0+=(*w)[j]*pGetExp(p,j+1);
1472    if(d0<d||d==-1)
1473      d=d0;
1474    pIter(p);
1475  }
1476  return d;
1477}
1478
1479poly pSeries(int n,poly p,poly u, intvec *w)
1480{
1481  short *ww=iv2array(w);
1482  if(p!=NULL)
1483  {
1484    if(u==NULL)
1485      p=pJetW(p,n,ww);
1486    else
1487      p=pJetW(pMult(p,pInvers(n-pMinDeg(p,w),u,w)),n,ww);
1488  }
1489  omFreeSize((ADDRESS)ww,(pVariables+1)*sizeof(short));
1490  return p;
1491}
1492
1493poly pInvers(int n,poly u,intvec *w)
1494{
1495  short *ww=iv2array(w);
1496  if(n<0)
1497    return NULL;
1498  number u0=nInvers(pGetCoeff(u));
1499  poly v=pNSet(u0);
1500  if(n==0)
1501    return v;
1502  poly u1=pJetW(pSub(pOne(),pMult_nn(u,u0)),n,ww);
1503  if(u1==NULL)
1504    return v;
1505  poly v1=pMult_nn(pCopy(u1),u0);
1506  v=pAdd(v,pCopy(v1));
1507  for(int i=n/pMinDeg(u1,w);i>1;i--)
1508  {
1509    v1=pJetW(pMult(v1,pCopy(u1)),n,ww);
1510    v=pAdd(v,pCopy(v1));
1511  }
1512  pDelete(&u1);
1513  pDelete(&v1);
1514  omFreeSize((ADDRESS)ww,(pVariables+1)*sizeof(short));
1515  return v;
1516}
1517
1518long pDegW(poly p, const short *w)
1519{
1520  long r=-LONG_MAX;
1521
1522  while (p!=NULL)
1523  {
1524    long t=totaldegreeWecart_IV(p,currRing,w);
1525    if (t>r) r=t;
1526    pIter(p);
1527  }
1528  return r;
1529}
1530
1531/*-----------type conversions ----------------------------*/
1532#if 0
1533/*2
1534* input: a set of polys (len elements: p[0]..p[len-1])
1535* output: a vector
1536* p will not be changed
1537*/
1538poly  pPolys2Vec(polyset p, int len)
1539{
1540  poly v=NULL;
1541  poly h;
1542  int i;
1543
1544  for (i=len-1; i>=0; i--)
1545  {
1546    if (p[i])
1547    {
1548      h=pCopy(p[i]);
1549      pSetCompP(h,i+1);
1550      v=pAdd(v,h);
1551    }
1552  }
1553 return v;
1554}
1555#endif
1556
1557/*2
1558* convert a vector to a set of polys,
1559* allocates the polyset, (entries 0..(*len)-1)
1560* the vector will not be changed
1561*/
1562void  pVec2Polys(poly v, polyset *p, int *len)
1563{
1564  poly h;
1565  int k;
1566
1567  *len=pMaxComp(v);
1568  if (*len==0) *len=1;
1569  *p=(polyset)omAlloc0((*len)*sizeof(poly));
1570  while (v!=NULL)
1571  {
1572    h=pHead(v);
1573    k=pGetComp(h);
1574    pSetComp(h,0);
1575    (*p)[k-1]=pAdd((*p)[k-1],h);
1576    pIter(v);
1577  }
1578}
1579
1580int p_Var(poly m,const ring r)
1581{
1582  if (m==NULL) return 0;
1583  if (pNext(m)!=NULL) return 0;
1584  int i,e=0;
1585  for (i=r->N; i>0; i--)
1586  {
1587    int exp=p_GetExp(m,i,r);
1588    if (exp==1)
1589    {
1590      if (e==0) e=i;
1591      else return 0;
1592    }
1593    else if (exp!=0)
1594    {
1595      return 0;
1596    }
1597  }
1598  return e;
1599}
1600
1601/*----------utilities for syzygies--------------*/
1602//BOOLEAN   pVectorHasUnitM(poly p, int * k)
1603//{
1604//  while (p!=NULL)
1605//  {
1606//    if (pLmIsConstantComp(p))
1607//    {
1608//      *k = pGetComp(p);
1609//      return TRUE;
1610//    }
1611//    else pIter(p);
1612//  }
1613//  return FALSE;
1614//}
1615
1616BOOLEAN   pVectorHasUnitB(poly p, int * k)
1617{
1618  poly q=p,qq;
1619  int i;
1620
1621  while (q!=NULL)
1622  {
1623    if (pLmIsConstantComp(q))
1624    {
1625      i = pGetComp(q);
1626      qq = p;
1627      while ((qq != q) && (pGetComp(qq) != i)) pIter(qq);
1628      if (qq == q)
1629      {
1630        *k = i;
1631        return TRUE;
1632      }
1633      else
1634        pIter(q);
1635    }
1636    else pIter(q);
1637  }
1638  return FALSE;
1639}
1640
1641void   pVectorHasUnit(poly p, int * k, int * len)
1642{
1643  poly q=p,qq;
1644  int i,j=0;
1645
1646  *len = 0;
1647  while (q!=NULL)
1648  {
1649    if (pLmIsConstantComp(q))
1650    {
1651      i = pGetComp(q);
1652      qq = p;
1653      while ((qq != q) && (pGetComp(qq) != i)) pIter(qq);
1654      if (qq == q)
1655      {
1656       j = 0;
1657       while (qq!=NULL)
1658       {
1659         if (pGetComp(qq)==i) j++;
1660        pIter(qq);
1661       }
1662       if ((*len == 0) || (j<*len))
1663       {
1664         *len = j;
1665         *k = i;
1666       }
1667      }
1668    }
1669    pIter(q);
1670  }
1671}
1672
1673/*2
1674* returns TRUE if p1 = p2
1675*/
1676BOOLEAN p_EqualPolys(poly p1,poly p2, const ring r)
1677{
1678  while ((p1 != NULL) && (p2 != NULL))
1679  {
1680    if (! p_LmEqual(p1, p2,r))
1681      return FALSE;
1682    if (! n_Equal(p_GetCoeff(p1,r), p_GetCoeff(p2,r),r ))
1683      return FALSE;
1684    pIter(p1);
1685    pIter(p2);
1686  }
1687  return (p1==p2);
1688}
1689
1690/*2
1691*returns TRUE if p1 is a skalar multiple of p2
1692*assume p1 != NULL and p2 != NULL
1693*/
1694BOOLEAN pComparePolys(poly p1,poly p2)
1695{
1696  number n,nn;
1697  pAssume(p1 != NULL && p2 != NULL);
1698
1699  if (!pLmEqual(p1,p2)) //compare leading mons
1700      return FALSE;
1701  if ((pNext(p1)==NULL) && (pNext(p2)!=NULL))
1702     return FALSE;
1703  if ((pNext(p2)==NULL) && (pNext(p1)!=NULL))
1704     return FALSE;
1705  if (pLength(p1) != pLength(p2))
1706    return FALSE;
1707#ifdef HAVE_RINGS
1708  if (rField_is_Ring(currRing))
1709  {
1710    if (!nDivBy(pGetCoeff(p1), pGetCoeff(p2))) return FALSE;
1711  }
1712#endif
1713  n=nDiv(pGetCoeff(p1),pGetCoeff(p2));
1714  while ((p1 != NULL) /*&& (p2 != NULL)*/)
1715  {
1716    if ( ! pLmEqual(p1, p2))
1717    {
1718        nDelete(&n);
1719        return FALSE;
1720    }
1721    if (!nEqual(pGetCoeff(p1),nn=nMult(pGetCoeff(p2),n)))
1722    {
1723      nDelete(&n);
1724      nDelete(&nn);
1725      return FALSE;
1726    }
1727    nDelete(&nn);
1728    pIter(p1);
1729    pIter(p2);
1730  }
1731  nDelete(&n);
1732  return TRUE;
1733}
Note: See TracBrowser for help on using the repository browser.