source: git/kernel/polys1.cc @ a5d9313

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