source: git/kernel/longalg.cc @ 8fbdb2

fieker-DuValspielwiese
Last change on this file since 8fbdb2 was 8fa1c2, checked in by Hans Schönemann <hannes@…>, 17 years ago
*hannes: optim, ->s git-svn-id: file:///usr/local/Singular/svn/trunk@9782 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 47.0 KB
Line 
1/****************************************
2*  Computer Algebra System SINGULAR     *
3****************************************/
4/* $Id: longalg.cc,v 1.21 2007-01-30 09:30:16 Singular Exp $ */
5/*
6* ABSTRACT:   algebraic numbers
7*/
8
9#include <stdio.h>
10#include <string.h>
11#include "mod2.h"
12#include "structs.h"
13#include "omalloc.h"
14#include "febase.h"
15#include "longrat.h"
16#include "modulop.h"
17#include "numbers.h"
18#include "polys.h"
19#include "ideals.h"
20#include "ring.h"
21#ifdef HAVE_FACTORY
22#include "factory.h"
23#include "clapsing.h"
24#include "clapconv.h"
25#endif
26#include "longalg.h"
27
28naIdeal naI=NULL;
29
30int naNumbOfPar;
31napoly naMinimalPoly;
32#define naParNames (currRing->parameter)
33#define napNormalize(p) p_Normalize(p,nacRing)
34static int naIsChar0;
35static int naPrimeM;
36
37#ifdef LDEBUG
38#define naTest(a) naDBTest(a,__FILE__,__LINE__)
39BOOLEAN naDBTest(number a, char *f,int l);
40#else
41#define naTest(a)
42#endif
43
44number (*naMap)(number from);
45/* procedure variables */
46static numberfunc
47                nacMult, nacSub, nacAdd, nacDiv, nacIntDiv;
48static number   (*nacGcd)(number a, number b, const ring r);
49static number   (*nacLcm)(number a, number b, const ring r);
50static void     (*nacDelete)(number *a, const ring r);
51       number   (*nacInit)(int i);
52static int      (*nacInt)(number &n);
53       void     (*nacNormalize)(number &a);
54static number   (*nacNeg)(number a);
55static void     (*nacWrite)(number &a);
56       number   (*nacCopy)(number a);
57static number   (*nacInvers)(number a);
58       BOOLEAN  (*nacIsZero)(number a);
59static BOOLEAN  (*nacIsOne)(number a);
60static BOOLEAN  (*nacIsMOne)(number a);
61static BOOLEAN  (*nacGreaterZero)(number a);
62static char   * (*nacRead) (char *s, number *a);
63static napoly napRedp(napoly q);
64static napoly napTailred(napoly q);
65static BOOLEAN napDivPoly(napoly p, napoly q);
66static int napExpi(int i, napoly a, napoly b);
67static ring nacRing;
68
69#define napCopy(p)       (napoly)p_Copy((poly)p,nacRing)
70
71static number nadGcd( number a, number b, const ring r) { return nacInit(1); }
72/*2
73*  sets the appropriate operators
74*/
75void naSetChar(int i, ring r)
76{
77  if (naI!=NULL)
78  {
79    int j;
80    for (j=naI->anz-1; j>=0; j--)
81       napDelete (&naI->liste[j]);
82    omFreeSize((ADDRESS)naI->liste,naI->anz*sizeof(napoly));
83    omFreeBin((ADDRESS)naI, snaIdeal_bin);
84    naI=NULL;
85  }
86  naMap = naCopy;
87
88  if (r->minpoly!=NULL)
89  {
90    naMinimalPoly=((lnumber)r->minpoly)->z;
91    omCheckAddr(naMinimalPoly);
92  }
93  else
94    naMinimalPoly = NULL;
95  if (r->minideal!=NULL)
96  {
97    naI=(naIdeal)omAllocBin(snaIdeal_bin);
98    naI->anz=IDELEMS(r->minideal);
99    naI->liste=(napoly*)omAlloc(naI->anz*sizeof(napoly));
100    int j;
101    for (j=naI->anz-1; j>=0; j--)
102    {
103      lnumber a = (lnumber)pGetCoeff(r->minideal->m[j]);
104      naI->liste[j]=napCopy(a->z);
105    }
106  }
107
108  naNumbOfPar=rPar(r);
109  if (i == 1)
110  {
111    naIsChar0 = 1;
112  }
113  else if (i < 0)
114  {
115    naIsChar0 = 0;
116    npSetChar(-i, r->algring); // to be changed HS
117  }
118#ifdef TEST
119  else
120  {
121    Print("naSetChar:c=%d param=%d\n",i,rPar(r));
122  }
123#endif
124  nacRing        = r->algring;
125  nacInit        = nacRing->cf->nInit;
126  nacInt         = nacRing->cf->nInt;
127  nacCopy        = nacRing->cf->nCopy;
128  nacAdd         = nacRing->cf->nAdd;
129  nacSub         = nacRing->cf->nSub;
130  nacNormalize   = nacRing->cf->nNormalize;
131  nacNeg         = nacRing->cf->nNeg;
132  nacIsZero      = nacRing->cf->nIsZero;
133  nacRead        = nacRing->cf->nRead;
134  nacWrite       = nacRing->cf->nWrite;
135  nacGreaterZero = nacRing->cf->nGreaterZero;
136  nacIsOne       = nacRing->cf->nIsOne;
137  nacIsMOne      = nacRing->cf->nIsMOne;
138  nacGcd         = nacRing->cf->nGcd;
139  nacLcm         = nacRing->cf->nLcm;
140  nacDelete      = nacRing->cf->cfDelete;
141  nacMult        = nacRing->cf->nMult;
142  nacDiv         = nacRing->cf->nDiv;
143  nacIntDiv      = nacRing->cf->nIntDiv;
144  nacInvers      = nacRing->cf->nInvers;
145}
146
147/*============= procedure for polynomials: napXXXX =======================*/
148
149
150
151#ifdef LDEBUG
152static void napTest(napoly p)
153{
154  while (p != NULL)
155  {
156    if (naIsChar0)
157      nlDBTest(napGetCoeff(p), "", 0);
158    napIter(p);
159  }
160}
161#else
162#define napTest(p) ((void) 0)
163#endif
164
165#define napInit(i)       (napoly)p_ISet(i,nacRing)
166#define napSetCoeff(p,n) {nacDelete(&napGetCoeff(p),nacRing);napGetCoeff(p)=n;}
167#define napDelete1(p)    p_LmDelete((poly *)p, nacRing)
168#define nap_Copy(p,r)       (napoly)p_Copy((poly)p,r->algring)
169#define napComp(p,q)     p_LmCmp((poly)p,(poly)q, nacRing)
170#define napMultT(A,E)    A=(napoly)p_Mult_mm((poly)A,(poly)E,nacRing)
171#define napMult(A,B)     (napoly)p_Mult_q((poly)A,(poly)B,nacRing)
172#define napMultCopy(A,B)   (napoly)pp_Mult_qq((poly)A,(poly)B,nacRing)
173#define napIsConstant(p) p_LmIsConstant(p,nacRing)
174#define napDeg(p)        (int)p_ExpVectorQuerSum(p, nacRing)
175
176/*3
177* creates  an napoly
178*/
179napoly napInitz(number z)
180{
181  napoly a = (napoly)p_Init(nacRing);
182  napGetCoeff(a) = z;
183  return a;
184}
185
186/*3
187* copy a napoly. poly
188*/
189static napoly napCopyNeg(napoly p)
190{
191  napoly r=napCopy(p);
192  r=(napoly)p_Neg((poly)r, nacRing);
193  return r;
194}
195
196/*3
197* returns ph * z
198*/
199static void napMultN(napoly p, number z)
200{
201  number t;
202
203  while (p!=NULL)
204  {
205    t = nacMult(napGetCoeff(p), z);
206    nacNormalize(t);
207    nacDelete(&napGetCoeff(p),nacRing);
208    napGetCoeff(p) = t;
209    napIter(p);
210  }
211}
212
213/*3
214*  division with rest; f = g*q + r, returns r and destroy f
215*/
216napoly napRemainder(napoly f, const napoly  g)
217{
218  napoly a, h, qq;
219
220  qq = (napoly)p_Init(nacRing);
221  napNext(qq) = NULL;
222  napNormalize(g);
223  napNormalize(f);
224  a = f;
225  do
226  {
227    napSetExp(qq,1, napGetExp(a,1) - napGetExp(g,1));
228    napSetm(qq);
229    napGetCoeff(qq) = nacDiv(napGetCoeff(a), napGetCoeff(g));
230    napGetCoeff(qq) = nacNeg(napGetCoeff(qq));
231    nacNormalize(napGetCoeff(qq));
232    h = napCopy(g);
233    napMultT(h, qq);
234    napNormalize(h);
235    nacDelete(&napGetCoeff(qq),nacRing);
236    a = napAdd(a, h);
237  }
238  while ((a!=NULL) && (napGetExp(a,1) >= napGetExp(g,1)));
239  omFreeBinAddr(qq);
240  return a;
241}
242
243/*3
244*  division with rest; f = g*q + r,  destroy f
245*/
246static void napDivMod(napoly f, napoly  g, napoly *q, napoly *r)
247{
248  napoly a, h, b, qq;
249
250  qq = (napoly)p_Init(nacRing);
251  napNext(qq) = b = NULL;
252  napNormalize(g);
253  napNormalize(f);
254  a = f;
255  do
256  {
257    napSetExp(qq,1, napGetExp(a,1) - napGetExp(g,1));
258    p_Setm(qq,nacRing);
259    napGetCoeff(qq) = nacDiv(napGetCoeff(a), napGetCoeff(g));
260    nacNormalize(napGetCoeff(qq));
261    b = napAdd(b, napCopy(qq));
262    napGetCoeff(qq) = nacNeg(napGetCoeff(qq));
263    h = napCopy(g);
264    napMultT(h, qq);
265    napNormalize(h);
266    nacDelete(&napGetCoeff(qq),nacRing);
267    a = napAdd(a, h);
268  }
269  while ((a!=NULL) && (napGetExp(a,1) >= napGetExp(g,1)));
270  omFreeBinAddr(qq);
271  *q = b;
272  *r = a;
273}
274
275/*3
276*  returns z with z*x mod c = 1
277*/
278static napoly napInvers(napoly x, const napoly c)
279{
280  napoly y, r, qa, qn, q;
281  number t, h;
282
283  if (napGetExp(x,1) >= napGetExp(c,1))
284    x = napRemainder(x, c);
285  if (x==NULL)
286  {
287    goto zero_divisor;
288  }
289  if (napGetExp(x,1)==0)
290  {
291    if (!nacIsOne(napGetCoeff(x)))
292    {
293      nacNormalize(napGetCoeff(x));
294      t = nacInvers(napGetCoeff(x));
295      nacNormalize(t);
296      nacDelete(&napGetCoeff(x),nacRing);
297      napGetCoeff(x) = t;
298    }
299    return x;
300  }
301  y = napCopy(c);
302  napDivMod(y, x, &qa, &r);
303  if (r==NULL)
304  {
305    goto zero_divisor;
306  }
307  if (napGetExp(r,1)==0)
308  {
309    nacNormalize(napGetCoeff(r));
310    t = nacInvers(napGetCoeff(r));
311    nacNormalize(t);
312    t = nacNeg(t);
313    napMultN(qa, t);
314    nacDelete(&t,nacRing);
315    napNormalize(qa);
316    napDelete(&x);
317    napDelete(&r);
318    return qa;
319  }
320  y = x;
321  x = r;
322  napDivMod(y, x, &q, &r);
323  if (r==NULL)
324  {
325    goto zero_divisor;
326  }
327  if (napGetExp(r,1)==0)
328  {
329    q = napMult(q, qa);
330    q = napAdd(q, napInit(1));
331    nacNormalize(napGetCoeff(r));
332    t = nacInvers(napGetCoeff(r));
333    napMultN(q, t);
334    napNormalize(q);
335    nacDelete(&t,nacRing);
336    napDelete(&x);
337    napDelete(&r);
338    if (napGetExp(q,1) >= napGetExp(c,1))
339      q = napRemainder(q, c);
340    return q;
341  }
342  q = napMult(q, napCopy(qa));
343  q = napAdd(q, napInit(1));
344  qa = napNeg(qa);
345  loop
346  {
347    y = x;
348    x = r;
349    napDivMod(y, x, &qn, &r);
350    if (r==NULL)
351    {
352      break;
353    }
354    if (napGetExp(r,1)==0)
355    {
356      q = napMult(q, qn);
357      q = napNeg(q);
358      q = napAdd(q, qa);
359      nacNormalize(napGetCoeff(r));
360      t = nacInvers(napGetCoeff(r));
361      //nacNormalize(t);
362      napMultN(q, t);
363      napNormalize(q);
364      nacDelete(&t,nacRing);
365      napDelete(&x);
366      napDelete(&r);
367      if (napGetExp(q,1) >= napGetExp(c,1))
368        q = napRemainder(q, c);
369      return q;
370    }
371    y = q;
372    q = napMult(napCopy(q), qn);
373    q = napNeg(q);
374    q = napAdd(q, qa);
375    qa = y;
376  }
377// zero divisor found:
378zero_divisor:
379  Werror("zero divisor found - your minpoly is not irreducible");
380  return x;
381}
382
383/*3
384* the max degree of an napoly poly (used for test of "simple" et al.)
385*/
386static int  napMaxDeg(napoly p)
387{
388  int  d = 0;
389  while(p!=NULL)
390  {
391    d=si_max(d,napDeg(p));
392    napIter(p);
393  }
394  return d;
395}
396
397/*3
398* the max degree of an napoly poly (used for test of "simple" et al.)
399*/
400static int  napMaxDegLen(napoly p, int &l)
401{
402  int  d = 0;
403  int ll=0;
404  while(p!=NULL)
405  {
406    d=si_max(d,napDeg(p));
407    napIter(p);
408    ll++;
409  }
410  l=ll;
411  return d;
412}
413
414
415/*3
416*writes a polynomial number
417*/
418void napWrite(napoly p,const BOOLEAN has_denom)
419{
420  if (p==NULL)
421    StringAppendS("0");
422  else if (napIsConstant(p))
423  {
424    BOOLEAN kl=FALSE;
425    if (has_denom)
426    {
427      number den=nacRing->cf->n_GetDenom(napGetCoeff(p), nacRing);
428      kl=!n_IsOne(den,nacRing);
429      n_Delete(&den, nacRing);
430    }
431    if (kl) StringAppendS("(");
432    //StringAppendS("-1");
433    nacWrite(napGetCoeff(p));
434    if (kl) StringAppendS(")");
435  }
436  else
437  {
438    StringAppendS("(");
439    loop
440    {
441      BOOLEAN wroteCoeff=FALSE;
442      if ((napIsConstant(p))
443      || ((!nacIsOne(napGetCoeff(p)))
444        && (!nacIsMOne(napGetCoeff(p)))))
445      {
446        nacWrite(napGetCoeff(p));
447        wroteCoeff=(currRing->ShortOut==0);
448      }
449      else if (nacIsMOne(napGetCoeff(p)))
450      {
451        StringAppendS("-");
452      }
453      int  i;
454      for (i = 0; i < naNumbOfPar; i++)
455      {
456        if (napGetExp(p,i+1) > 0)
457        {
458          if (wroteCoeff)
459            StringAppendS("*");
460          else
461            wroteCoeff=(currRing->ShortOut==0);
462          StringAppendS(naParNames[i]);
463          if (napGetExp(p,(i+1)) > 1)
464          {
465            if (currRing->ShortOut == 0)
466              StringAppendS("^");
467            StringAppend("%d", napGetExp(p,i+1));
468          }
469        }
470      } /*for*/
471      napIter(p);
472      if (p==NULL)
473        break;
474      if (nacGreaterZero(napGetCoeff(p)))
475        StringAppendS("+");
476    }
477    StringAppendS(")");
478  }
479}
480
481
482static char *napHandleMons(char *s, int i, napoly ex)
483{
484  int  j;
485  if (strncmp(s,naParNames[i],strlen(naParNames[i]))==0)
486  {
487    s+=strlen(naParNames[i]);
488    if ((*s >= '0') && (*s <= '9'))
489    {
490      s = eati(s, &j);
491      napAddExp(ex,i+1,j);
492    }
493    else
494      napAddExp(ex,i+1,1);
495  }
496  return s;
497}
498
499/*3  reads a monomial  */
500static char  *napRead(char *s, napoly *b)
501{
502  napoly a;
503  int  i;
504  a = (napoly)p_Init(nacRing);
505  if ((*s >= '0') && (*s <= '9'))
506  {
507    s = nacRead(s, &napGetCoeff(a));
508    if (nacIsZero(napGetCoeff(a)))
509    {
510      napDelete1(&a);
511      *b = NULL;
512      return s;
513    }
514  }
515  else
516    napGetCoeff(a) = nacInit(1);
517  i = 0;
518  char  *olds;
519  loop
520  {
521    olds = s;
522    s = napHandleMons(s, i, a);
523    if (olds == s)
524      i++;
525    else
526      i = 0;
527    if ((*s == '\0') || (i >= naNumbOfPar))
528      break;
529  }
530  *b = a;
531  return s;
532}
533
534static int napExp(napoly a, napoly b)
535{
536  while (napNext(a)!=NULL) napIter(a);
537  int m = napGetExp(a,1);
538  if (m==0) return 0;
539  while (napNext(b)!=NULL) napIter(b);
540  int mm=napGetExp(b,1);
541  if (m > mm) m = mm;
542  return m;
543}
544
545/*
546* finds the smallest i-th exponent in a and b
547* used to find it in a fraction
548*/
549static int napExpi(int i, napoly a, napoly b)
550{
551  if (a==NULL || b==NULL) return 0;
552  int m = napGetExp(a,i+1);
553  if (m==0) return 0;
554  while (napNext(a) != NULL)
555  {
556    napIter(a);
557    if (m > napGetExp(a,i+1))
558    {
559      m = napGetExp(a,i+1);
560      if (m==0) return 0;
561    }
562  }
563  do
564  {
565    if (m > napGetExp(b,i+1))
566    {
567      m = napGetExp(b,i+1);
568      if (m==0) return 0;
569    }
570    napIter(b);
571  }
572  while (b != NULL);
573  return m;
574}
575
576static void napContent(napoly ph)
577{
578  number h,d;
579  napoly p;
580
581  p = ph;
582  if (nacIsOne(napGetCoeff(p)))
583    return;
584  h = nacCopy(napGetCoeff(p));
585  napIter(p);
586  do
587  {
588    d=nacGcd(napGetCoeff(p), h, nacRing);
589    if(nacIsOne(d))
590    {
591      nacDelete(&h,nacRing);
592      nacDelete(&d,nacRing);
593      return;
594    }
595    nacDelete(&h,nacRing);
596    h = d;
597    napIter(p);
598  }
599  while (p!=NULL);
600  h = nacInvers(d);
601  nacDelete(&d,nacRing);
602  p = ph;
603  while (p!=NULL)
604  {
605    d = nacMult(napGetCoeff(p), h);
606    nacDelete(&napGetCoeff(p),nacRing);
607    napGetCoeff(p) = d;
608    napIter(p);
609  }
610  nacDelete(&h,nacRing);
611}
612
613static void napCleardenom(napoly ph)
614{
615  number d, h;
616  napoly p;
617
618  if (!naIsChar0)
619    return;
620  p = ph;
621  h = nacInit(1);
622  while (p!=NULL)
623  {
624    d = nacLcm(h, napGetCoeff(p), nacRing);
625    nacDelete(&h,nacRing);
626    h = d;
627    napIter(p);
628  }
629  if(!nacIsOne(h))
630  {
631    p = ph;
632    while (p!=NULL)
633    {
634      d=nacMult(h, napGetCoeff(p));
635      nacDelete(&napGetCoeff(p),nacRing);
636      nacNormalize(d);
637      napGetCoeff(p) = d;
638      napIter(p);
639    }
640    nacDelete(&h,nacRing);
641  }
642  napContent(ph);
643}
644
645static napoly napGcd0(napoly a, napoly b)
646{
647  number x, y;
648  if (!naIsChar0)
649    return napInit(1);
650  x = nacCopy(napGetCoeff(a));
651  if (nacIsOne(x))
652    return napInitz(x);
653  while (napNext(a)!=NULL)
654  {
655    napIter(a);
656    y = nacGcd(x, napGetCoeff(a), nacRing);
657    nacDelete(&x,nacRing);
658    x = y;
659    if (nacIsOne(x))
660      return napInitz(x);
661  }
662  do
663  {
664    y = nacGcd(x, napGetCoeff(b), nacRing);
665    nacDelete(&x,nacRing);
666    x = y;
667    if (nacIsOne(x))
668      return napInitz(x);
669    napIter(b);
670  }
671  while (b!=NULL);
672  return napInitz(x);
673}
674
675/*3
676* result =gcd(a,b)
677*/
678static napoly napGcd(napoly a, napoly b)
679{
680  int i;
681  napoly g, x, y, h;
682  if ((a==NULL)
683  || ((napNext(a)==NULL)&&(nacIsZero(napGetCoeff(a)))))
684  {
685    if ((b==NULL)
686    || ((napNext(b)==NULL)&&(nacIsZero(napGetCoeff(b)))))
687    {
688      return napInit(1);
689    }
690    return napCopy(b);
691  }
692  else
693  if ((b==NULL)
694  || ((napNext(b)==NULL)&&(nacIsZero(napGetCoeff(b)))))
695  {
696    return napCopy(a);
697  }
698  if (naMinimalPoly != NULL)
699  {
700    if (napGetExp(a,1) >= napGetExp(b,1))
701    {
702      x = a;
703      y = b;
704    }
705    else
706    {
707      x = b;
708      y = a;
709    }
710    if (!naIsChar0) g = napInit(1);
711    else            g = napGcd0(x, y);
712    if (napNext(y)==NULL)
713    {
714      napSetExp(g,1, napExp(x, y));
715      p_Setm(g,nacRing);
716      return g;
717    }
718    x = napCopy(x);
719    y = napCopy(y);
720    loop
721    {
722      h = napRemainder(x, y);
723      if (h==NULL)
724      {
725        napCleardenom(y);
726        if (!nacIsOne(napGetCoeff(g)))
727          napMultN(y, napGetCoeff(g));
728        napDelete1(&g);
729        return y;
730      }
731      else if (napNext(h)==NULL)
732        break;
733      x = y;
734      y = h;
735    }
736    napDelete(&y);
737    napDelete1(&h);
738    napSetExp(g,1, napExp(a, b));
739    p_Setm(g,nacRing);
740    return g;
741  }
742  // Hmm ... this is a memory leak
743  // x = (napoly)p_Init(nacRing);
744  g=a;
745  h=b;
746  if (!naIsChar0) x = napInit(1);
747  else            x = napGcd0(g,h);
748  for (i=(naNumbOfPar-1); i>=0; i--)
749  {
750    napSetExp(x,i+1, napExpi(i,a,b));
751    p_Setm(x,nacRing);
752  }
753  return x;
754}
755
756
757number napLcm(napoly a)
758{
759  number h = nacInit(1);
760
761  if (naIsChar0)
762  {
763    number d;
764    napoly b = a;
765
766    while (b!=NULL)
767    {
768      d = nacLcm(h, napGetCoeff(b), nacRing);
769      nacDelete(&h,nacRing);
770      h = d;
771      napIter(b);
772    }
773  }
774  return h;
775}
776
777
778/*2
779* meins  (for reduction in algebraic extension)
780* checks if head of p divides head of q
781* doesn't delete p and q
782*/
783static BOOLEAN napDivPoly (napoly p, napoly q)
784{
785  int j=1;   /* evtl. von naNumber.. -1 abwaerts zaehlen */
786
787  while (napGetExp(p,j) <= napGetExp(q,j))
788  {
789    j++;
790    if (j > naNumbOfPar)
791      return 1;
792  }
793  return 0;
794}
795
796
797/*2
798* meins  (for reduction in algebraic extension)
799* Normalform of poly with naI
800* changes q and returns it
801*/
802napoly napRedp (napoly q)
803{
804  napoly h = (napoly)p_Init(nacRing);
805  int i=0,j;
806
807  loop
808  {
809    if (napDivPoly (naI->liste[i], q))
810    {
811      /* h = lt(q)/lt(naI->liste[i])*/
812      napGetCoeff(h) = nacCopy(napGetCoeff(q));
813      for (j=naNumbOfPar; j>0; j--)
814        napSetExp(h,j, napGetExp(q,j) - napGetExp(naI->liste[i],j));
815      p_Setm(h,nacRing);
816      h = napMult (h, napCopy(naI->liste[i]));
817      h = napNeg (h);
818      q = napAdd (q, napCopy(h));
819      napDelete (&napNext(h));
820      if (q == NULL)
821      {
822        napDelete(&h);
823        return q;
824      }
825      /* try to reduce further */
826      i = 0;
827    }
828    else
829    {
830      i++;
831      if (i >= naI->anz)
832      {
833        napDelete(&h);
834        return q;
835      }
836    }
837  }
838}
839
840
841/*2
842* meins  (for reduction in algebraic extension)
843* reduces the tail of Poly q
844* needs q != NULL
845* changes q and returns it
846*/
847napoly napTailred (napoly q)
848{
849  napoly h;
850
851  h = napNext(q);
852  while (h != NULL)
853  {
854     h = napRedp (h);
855     if (h == NULL)
856        return q;
857     napIter(h);
858  }
859  return q;
860}
861
862
863/*================ procedure for rational functions: naXXXX =================*/
864
865/*2
866*  z:= i
867*/
868number naInit(int i)
869{
870  if (i!=0)
871  {
872    napoly z=napInit(i);
873    if (z!=NULL)
874    {
875      lnumber l = (lnumber)omAllocBin(rnumber_bin);
876      l->z = z;
877      l->s = 2;
878      l->n = NULL;
879      return (number)l;
880    }
881  }
882  /*else*/
883  return NULL;
884}
885
886number  naPar(int i)
887{
888  lnumber l = (lnumber)omAllocBin(rnumber_bin);
889  l->s = 2;
890  l->z = napInit(1);
891  napSetExp(l->z,i,1);
892  p_Setm(l->z,nacRing);
893  l->n = NULL;
894  return (number)l;
895}
896
897int     naParDeg(number n)     /* i := deg(n) */
898{
899  lnumber l = (lnumber)n;
900  if (l==NULL) return -1;
901  return napDeg(l->z);
902}
903
904//int     naParDeg(number n)     /* i := deg(n) */
905//{
906//  lnumber l = (lnumber)n;
907//  if (l==NULL) return -1;
908//  return napMaxDeg(l->z)+napMaxDeg(l->n);
909//}
910
911int     naSize(number n)     /* size desc. */
912{
913  lnumber l = (lnumber)n;
914  if (l==NULL) return -1;
915  int len_z;
916  int len_n;
917  int o=napMaxDegLen(l->z,len_z)+napMaxDegLen(l->n,len_n);
918  return (len_z+len_n)+o;
919}
920
921/*2
922* convert a number to int (if possible)
923*/
924int naInt(number &n)
925{
926  lnumber l=(lnumber)n;
927  if ((l!=NULL)&&(l->n==NULL)&&(napIsConstant(l->z)))
928  {
929    return nacInt(napGetCoeff(l->z));
930  }
931  return 0;
932}
933
934/*2
935*  deletes p
936*/
937void naDelete(number *p, const ring r)
938{
939  if ((*p)!=r->minpoly)
940  {
941    lnumber l = (lnumber) * p;
942    if (l==NULL) return;
943    nap_Delete(&(l->z),r);
944    nap_Delete(&(l->n),r);
945    omFreeBin((ADDRESS)l,  rnumber_bin);
946  }
947  *p = NULL;
948}
949
950/*2
951* copy p to erg
952*/
953number naCopy(number p)
954{
955  if (p==NULL) return NULL;
956  naTest(p);
957  lnumber erg;
958  lnumber src = (lnumber)p;
959  erg = (lnumber)omAlloc0Bin(rnumber_bin);
960  erg->z = napCopy(src->z);
961  erg->n = napCopy(src->n);
962  erg->s = src->s;
963  return (number)erg;
964}
965number na_Copy(number p, const ring r)
966{
967  if (p==NULL) return NULL;
968  lnumber erg;
969  lnumber src = (lnumber)p;
970  erg = (lnumber)omAlloc0Bin(rnumber_bin);
971  erg->z = nap_Copy(src->z,r);
972  erg->n = nap_Copy(src->n,r);
973  erg->s = src->s;
974  return (number)erg;
975}
976
977/*2
978* a dummy number: 0
979*/
980void naNew(number *z)
981{
982  *z = NULL;
983}
984
985/*2
986*  addition; lu:= la + lb
987*/
988number naAdd(number la, number lb)
989{
990  napoly x, y;
991  lnumber lu;
992  lnumber a = (lnumber)la;
993  lnumber b = (lnumber)lb;
994  if (a==NULL) return naCopy(lb);
995  if (b==NULL) return naCopy(la);
996  omCheckAddrSize(a,sizeof(snumber));
997  omCheckAddrSize(b,sizeof(snumber));
998  lu = (lnumber)omAllocBin(rnumber_bin);
999  if (b->n!=NULL) x = napMultCopy(a->z, b->n);
1000  else            x = napCopy(a->z);
1001  if (a->n!=NULL) y = napMultCopy(b->z, a->n);
1002  else            y = napCopy(b->z);
1003  lu->z = napAdd(x, y);
1004  if (lu->z==NULL)
1005  {
1006    omFreeBin((ADDRESS)lu,  rnumber_bin);
1007    return (number)NULL;
1008  }
1009  if (a->n!=NULL)
1010  {
1011    if (b->n!=NULL) x = napMultCopy(a->n, b->n);
1012    else            x = napCopy(a->n);
1013  }
1014  else
1015  {
1016    if (b->n!=NULL) x = napCopy(b->n);
1017    else            x = NULL;
1018  }
1019  if (x!=NULL)
1020  {
1021    assume(!napIsConstant(x));
1022  }
1023  lu->n = x;
1024  lu->s = 0;
1025  if (lu->n!=NULL)
1026  {
1027     number luu=(number)lu;
1028     naNormalize(luu);
1029     lu=(lnumber)luu;
1030  }
1031  naTest((number)lu);
1032  return (number)lu;
1033}
1034
1035/*2
1036*  subtraction; r:= la - lb
1037*/
1038number naSub(number la, number lb)
1039{
1040  lnumber lu;
1041
1042  if (lb==NULL) return naCopy(la);
1043  if (la==NULL)
1044  {
1045    lu = (lnumber)naCopy(lb);
1046    lu->z = napNeg(lu->z);
1047    return (number)lu;
1048  }
1049
1050  lnumber a = (lnumber)la;
1051  lnumber b = (lnumber)lb;
1052
1053  omCheckAddrSize(a,sizeof(snumber));
1054  omCheckAddrSize(b,sizeof(snumber));
1055
1056  napoly x, y;
1057  lu = (lnumber)omAllocBin(rnumber_bin);
1058  if (b->n!=NULL) x = napMultCopy(a->z, b->n);
1059  else            x = napCopy(a->z);
1060  if (a->n!=NULL) y = napMult(napCopy(b->z), napCopyNeg(a->n));
1061  else            y = napCopyNeg(b->z);
1062  lu->z = napAdd(x, y);
1063  if (lu->z==NULL)
1064  {
1065    omFreeBin((ADDRESS)lu,  rnumber_bin);
1066    return (number)NULL;
1067  }
1068  if (a->n!=NULL)
1069  {
1070    if (b->n!=NULL) x = napMultCopy(a->n, b->n);
1071    else            x = napCopy(a->n);
1072  }
1073  else
1074  {
1075    if (b->n!=NULL) x = napCopy(b->n);
1076    else            x = NULL;
1077  }
1078  if (x!=NULL)
1079  {
1080    assume(!napIsConstant(x));
1081  }
1082  lu->n = x;
1083  lu->s = 0;
1084  if (lu->n!=NULL)
1085  {
1086     number luu=(number)lu;
1087     naNormalize(luu);
1088     lu=(lnumber)luu;
1089  }
1090  naTest((number)lu);
1091  return (number)lu;
1092}
1093
1094/*2
1095*  multiplication; r:= la * lb
1096*/
1097number naMult(number la, number lb)
1098{
1099  if ((la==NULL) || (lb==NULL))
1100    return NULL;
1101
1102  lnumber a = (lnumber)la;
1103  lnumber b = (lnumber)lb;
1104  lnumber lo;
1105  napoly x;
1106
1107  omCheckAddrSize(a,sizeof(snumber));
1108  omCheckAddrSize(b,sizeof(snumber));
1109  naTest(la);
1110  naTest(lb);
1111
1112  lo = (lnumber)omAllocBin(rnumber_bin);
1113  lo->z = napMultCopy(a->z, b->z);
1114
1115  if (a->n==NULL)
1116  {
1117    if (b->n==NULL)
1118      x = NULL;
1119    else
1120      x = napCopy(b->n);
1121  }
1122  else
1123  {
1124    if (b->n==NULL)
1125    {
1126      x = napCopy(a->n);
1127    }
1128    else
1129    {
1130      x = napMultCopy(b->n, a->n);
1131    }
1132  }
1133  if (naMinimalPoly!=NULL)
1134  {
1135    if (napGetExp(lo->z,1) >= napGetExp(naMinimalPoly,1))
1136      lo->z = napRemainder(lo->z, naMinimalPoly);
1137    if ((x!=NULL) && (napGetExp(x,1) >= napGetExp(naMinimalPoly,1)))
1138      x = napRemainder(x, naMinimalPoly);
1139  }
1140  if (naI!=NULL)
1141  {
1142    lo->z = napRedp (lo->z);
1143    if (lo->z != NULL)
1144       lo->z = napTailred (lo->z);
1145    if (x!=NULL)
1146    {
1147      x = napRedp (x);
1148      if (x!=NULL)
1149        x = napTailred (x);
1150    }
1151  }
1152  if ((x!=NULL) && (napIsConstant(x)) && nacIsOne(napGetCoeff(x)))
1153    napDelete(&x);
1154  lo->n = x;
1155  if(lo->z==NULL)
1156  {
1157    omFreeBin((ADDRESS)lo, rnumber_bin);
1158    lo=NULL;
1159  }
1160#if 1
1161  else if (lo->n!=NULL)
1162  {
1163    lo->s = 0;
1164    number luu=(number)lo;
1165    naNormalize(luu);
1166    lo=(lnumber)luu;
1167  }
1168  else
1169    lo->s=3;
1170#endif
1171  naTest((number)lo);
1172  return (number)lo;
1173}
1174
1175number naIntDiv(number la, number lb)
1176{
1177  lnumber res;
1178  lnumber a = (lnumber)la;
1179  lnumber b = (lnumber)lb;
1180  if (a==NULL)
1181  {
1182    return NULL;
1183  }
1184  if (b==NULL)
1185  {
1186    WerrorS("div. by 0");
1187    return NULL;
1188  }
1189  naNormalize(la);
1190  assume(a->z!=NULL && b->z!=NULL);
1191  assume(a->n==NULL && b->n==NULL);
1192  res = (lnumber)omAllocBin(rnumber_bin);
1193  res->z = napCopy(a->z);
1194  res->n = napCopy(b->z);
1195  res->s = 0;
1196  number nres=(number)res;
1197  naNormalize(nres);
1198
1199  //napDelete(&res->n);
1200  naTest(nres);
1201  return nres;
1202}
1203
1204/*2
1205*  division; lo:= la / lb
1206*/
1207number naDiv(number la, number lb)
1208{
1209  lnumber lo;
1210  lnumber a = (lnumber)la;
1211  lnumber b = (lnumber)lb;
1212  napoly x;
1213
1214  if ((a==NULL) || (a->z==NULL))
1215    return NULL;
1216
1217  if ((b==NULL) || (b->z==NULL))
1218  {
1219    WerrorS("div. by 0");
1220    return NULL;
1221  }
1222  omCheckAddrSize(a,sizeof(snumber));
1223  omCheckAddrSize(b,sizeof(snumber));
1224  lo = (lnumber)omAllocBin(rnumber_bin);
1225  if (b->n!=NULL)
1226    lo->z = napMultCopy(a->z, b->n);
1227  else
1228    lo->z = napCopy(a->z);
1229  if (a->n!=NULL)
1230    x = napMultCopy(b->z, a->n);
1231  else
1232    x = napCopy(b->z);
1233  if (naMinimalPoly!=NULL)
1234  {
1235    if (napGetExp(lo->z,1) >= napGetExp(naMinimalPoly,1))
1236      lo->z = napRemainder(lo->z, naMinimalPoly);
1237    if (napGetExp(x,1) >= napGetExp(naMinimalPoly,1))
1238      x = napRemainder(x, naMinimalPoly);
1239  }
1240  if (naI!=NULL)
1241  {
1242    lo->z = napRedp (lo->z);
1243    if (lo->z != NULL)
1244       lo->z = napTailred (lo->z);
1245    if (x!=NULL)
1246    {
1247      x = napRedp (x);
1248      if (x!=NULL)
1249        x = napTailred (x);
1250    }
1251  }
1252  if ((napIsConstant(x)) && nacIsOne(napGetCoeff(x)))
1253    napDelete(&x);
1254  lo->n = x;
1255  if (lo->n!=NULL)
1256  {
1257    lo->s = 0;
1258    number luu=(number)lo;
1259    naNormalize(luu);
1260    lo=(lnumber)luu;
1261  }
1262  else
1263    lo->s=3;
1264  naTest((number)lo);
1265  return (number)lo;
1266}
1267
1268/*2
1269*  za:= - za
1270*/
1271number naNeg(number za)
1272{
1273  if (za!=NULL)
1274  {
1275    lnumber e = (lnumber)za;
1276    naTest(za);
1277    e->z = napNeg(e->z);
1278  }
1279  return za;
1280}
1281
1282/*2
1283* 1/a
1284*/
1285number naInvers(number a)
1286{
1287  lnumber lo;
1288  lnumber b = (lnumber)a;
1289  napoly x;
1290
1291  if (b==NULL)
1292  {
1293    WerrorS("div. by 0");
1294    return NULL;
1295  }
1296  omCheckAddrSize(b,sizeof(snumber));
1297  lo = (lnumber)omAlloc0Bin(rnumber_bin);
1298  lo->s = b->s;
1299  if (b->n!=NULL)
1300    lo->z = napCopy(b->n);
1301  else
1302    lo->z = napInit(1);
1303  x = b->z;
1304  if ((!napIsConstant(x)) || !nacIsOne(napGetCoeff(x)))
1305    x = napCopy(x);
1306  else
1307  {
1308    lo->n = NULL;
1309    naTest((number)lo);
1310    return (number)lo;
1311  }
1312  if (naMinimalPoly!=NULL)
1313  {
1314    x = napInvers(x, naMinimalPoly);
1315    x = napMult(x, lo->z);
1316    if (napGetExp(x,1) >= napGetExp(naMinimalPoly,1))
1317      x = napRemainder(x, naMinimalPoly);
1318    lo->z = x;
1319    lo->n = NULL;
1320    lo->s = 2;
1321    while (x!=NULL)
1322    {
1323      nacNormalize(napGetCoeff(x));
1324      napIter(x);
1325    }
1326  }
1327  else
1328    lo->n = x;
1329  if (lo->n!=NULL)
1330  {
1331     number luu=(number)lo;
1332     naNormalize(luu);
1333     lo=(lnumber)luu;
1334  }
1335  naTest((number)lo);
1336  return (number)lo;
1337}
1338
1339
1340BOOLEAN naIsZero(number za)
1341{
1342  lnumber zb = (lnumber)za;
1343  naTest(za);
1344#ifdef LDEBUG
1345  if ((zb!=NULL) && (zb->z==NULL)) WerrorS("internal zero error(2)");
1346#endif
1347  return ((zb==NULL) || (zb->z==NULL));
1348}
1349
1350
1351BOOLEAN naGreaterZero(number za)
1352{
1353  lnumber zb = (lnumber)za;
1354#ifdef LDEBUG
1355  if ((zb!=NULL) && (zb->z==NULL)) WerrorS("internal zero error(3)");
1356#endif
1357  naTest(za);
1358  if ((zb!=NULL) && (zb->z!=NULL))
1359  {
1360    return (nacGreaterZero(napGetCoeff(zb->z))||(!napIsConstant(zb->z)));
1361  }
1362  /* else */ return FALSE;
1363}
1364
1365
1366/*2
1367* a = b ?
1368*/
1369BOOLEAN naEqual (number a, number b)
1370{
1371  if(a==b) return TRUE;
1372  if((a==NULL)&&(b!=NULL)) return FALSE;
1373  if((b==NULL)&&(a!=NULL)) return FALSE;
1374
1375  lnumber aa=(lnumber)a;
1376  lnumber bb=(lnumber)b;
1377
1378  int an_deg=0;
1379  if(aa->n!=NULL)
1380    an_deg=napDeg(aa->n);
1381  int bn_deg=0;
1382  if(bb->n!=NULL)
1383    bn_deg=napDeg(bb->n);
1384  if(an_deg+napDeg(bb->z)!=bn_deg+napDeg(aa->z))
1385    return FALSE;
1386#if 0
1387  naNormalize(a);
1388  aa=(lnumber)a;
1389  naNormalize(b);
1390  bb=(lnumber)b;
1391  if((aa->n==NULL)&&(bb->n!=NULL)) return FALSE;
1392  if((bb->n==NULL)&&(aa->n!=NULL)) return FALSE;
1393  if(napComp(aa->z,bb->z)!=0) return FALSE;
1394  if((aa->n!=NULL) && (napComp(aa->n,bb->n))) return FALSE;
1395#endif
1396  number h = naSub(a, b);
1397  BOOLEAN bo = naIsZero(h);
1398  naDelete(&h,currRing);
1399  return bo;
1400}
1401
1402
1403BOOLEAN naGreater (number a, number b)
1404{
1405  if (naIsZero(a))
1406    return FALSE;
1407  if (naIsZero(b))
1408    return TRUE; /* a!= 0)*/
1409  return napDeg(((lnumber)a)->z)>napDeg(((lnumber)b)->z);
1410}
1411
1412/*2
1413* reads a number
1414*/
1415char  *naRead(char *s, number *p)
1416{
1417  napoly x;
1418  lnumber a;
1419  s = napRead(s, &x);
1420  if (x==NULL)
1421  {
1422    *p = NULL;
1423    return s;
1424  }
1425  *p = (number)omAlloc0Bin(rnumber_bin);
1426  a = (lnumber)*p;
1427  if ((naMinimalPoly!=NULL)
1428  && (napGetExp(x,1) >= napGetExp(naMinimalPoly,1)))
1429    a->z = napRemainder(x, naMinimalPoly);
1430  else if (naI!=NULL)
1431  {
1432    a->z = napRedp(x);
1433    if (a->z != NULL)
1434      a->z = napTailred (a->z);
1435  }
1436  else
1437    a->z = x;
1438  if(a->z==NULL)
1439  {
1440    omFreeBin((ADDRESS)*p, rnumber_bin);
1441    *p=NULL;
1442  }
1443  else
1444  {
1445    a->n = NULL;
1446    a->s = 0;
1447    naTest(*p);
1448  }
1449  return s;
1450}
1451
1452/*2
1453* tries to convert a number to a name
1454*/
1455char * naName(number n)
1456{
1457  lnumber ph = (lnumber)n;
1458  if ((ph==NULL)||(ph->z==NULL))
1459    return NULL;
1460  int i;
1461  char *s=(char *)omAlloc(4* naNumbOfPar);
1462  char *t=(char *)omAlloc(8);
1463  s[0]='\0';
1464  for (i = 0; i <= naNumbOfPar - 1; i++)
1465  {
1466    if (napGetExp(ph->z,i+1) > 0)
1467    {
1468      if (napGetExp(ph->z,i+1) >1)
1469      {
1470        sprintf(t,"%s%d",naParNames[i],(int)napGetExp(ph->z,i+1));
1471        strcat(s,t);
1472      }
1473      else
1474      {
1475        strcat(s,naParNames[i]);
1476      }
1477    }
1478  }
1479  omFreeSize((ADDRESS)t,8);
1480  if (s[0]=='\0')
1481  {
1482    omFree((ADDRESS)s);
1483    return NULL;
1484  }
1485  return s;
1486}
1487
1488/*2
1489*  writes a number
1490*/
1491void naWrite(number &phn)
1492{
1493  lnumber ph = (lnumber)phn;
1494  if ((ph==NULL)||(ph->z==NULL))
1495    StringAppendS("0");
1496  else
1497  {
1498    phn->s = 0;
1499    naNormalize(phn);
1500    BOOLEAN has_denom=(ph->n!=NULL);
1501    napWrite(ph->z,has_denom/*(ph->n!=NULL)*/);
1502    if (has_denom/*(ph->n!=NULL)*/)
1503    {
1504      StringAppendS("/");
1505      napWrite(ph->n,TRUE);
1506    }
1507  }
1508}
1509
1510/*2
1511* za == 1 ?
1512*/
1513BOOLEAN naIsOne(number za)
1514{
1515  lnumber a = (lnumber)za;
1516  napoly x, y;
1517  number t;
1518  if (a==NULL) return FALSE;
1519  omCheckAddrSize(a,sizeof(snumber));
1520#ifdef LDEBUG
1521  if (a->z==NULL) WerrorS("internal zero error(4)");
1522#endif
1523  if (a->n==NULL)
1524  {
1525    if (napIsConstant(a->z)) 
1526    {
1527#ifdef LDEBUG
1528       if (a->z==NULL) return FALSE;
1529       else 
1530#endif
1531         return nacIsOne(napGetCoeff(a->z));
1532    }
1533    else                 return FALSE;
1534  }
1535  x = a->z;
1536  y = a->n;
1537  do
1538  {
1539    if (napComp(x, y))
1540      return FALSE;
1541    else
1542    {
1543      t = nacSub(napGetCoeff(x), napGetCoeff(y));
1544      if (!nacIsZero(t))
1545      {
1546        nacDelete(&t,nacRing);
1547        return FALSE;
1548      }
1549      else
1550        nacDelete(&t,nacRing);
1551    }
1552    napIter(x);
1553    napIter(y);
1554  }
1555  while ((x!=NULL) && (y!=NULL));
1556  if ((x!=NULL) || (y!=NULL)) return FALSE;
1557  napDelete(&a->z);
1558  napDelete(&a->n);
1559  a->z = napInit(1);
1560  a->n = NULL;
1561  a->s = 2;
1562  return TRUE;
1563}
1564
1565/*2
1566* za == -1 ?
1567*/
1568BOOLEAN naIsMOne(number za)
1569{
1570  lnumber a = (lnumber)za;
1571  napoly x, y;
1572  number t;
1573  if (a==NULL) return FALSE;
1574  omCheckAddrSize(a,sizeof(snumber));
1575#ifdef LDEBUG
1576  if (a->z==NULL)
1577  {
1578    WerrorS("internal zero error(5)");
1579    return FALSE;
1580  }
1581#endif
1582  if (a->n==NULL)
1583  {
1584    if (napIsConstant(a->z)) return nacIsMOne(napGetCoeff(a->z));
1585    /*else                   return FALSE;*/
1586  }
1587  return FALSE;
1588}
1589
1590/*2
1591* returns the i-th power of p (i>=0)
1592*/
1593void naPower(number p, int i, number *rc)
1594{
1595  number x;
1596  *rc = naInit(1);
1597  for (; i > 0; i--)
1598  {
1599    x = naMult(*rc, p);
1600    naDelete(rc,currRing);
1601    *rc = x;
1602  }
1603}
1604
1605/*2
1606* result =gcd(a,b)
1607*/
1608number naGcd(number a, number b, const ring r)
1609{
1610  lnumber x, y;
1611  lnumber result = (lnumber)omAlloc0Bin(rnumber_bin);
1612
1613  x = (lnumber)a;
1614  y = (lnumber)b;
1615  if ((naNumbOfPar == 1) && (naMinimalPoly!=NULL))
1616  {
1617    if (napNext(x->z)!=NULL)
1618      result->z = napCopy(x->z);
1619    else
1620      result->z = napGcd0(x->z, y->z);
1621  }
1622  else
1623#if 0
1624    result->z = napGcd(x->z, y->z); // change from napGcd0
1625#else
1626  {
1627    napoly rz=napGcd(x->z, y->z);
1628    CanonicalForm F, G, R;
1629    R=convSingTrClapP(rz); 
1630    napNormalize(x->z);
1631    F=convSingTrClapP(x->z)/R; 
1632    napNormalize(y->z);
1633    G=convSingTrClapP(y->z)/R; 
1634    F = gcd( F, G );
1635    if (F.isOne()) 
1636      result->z= rz;
1637    else
1638    {
1639      napDelete(&rz);
1640      result->z=convClapPSingTr( F*R );
1641      napNormalize(result->z);
1642    }
1643  }
1644#endif
1645
1646  naTest((number)result);
1647  return (number)result;
1648}
1649
1650/*2
1651* naNumbOfPar = 1:
1652* clears denominator         algebraic case;
1653* tries to simplify ratio    transcendental case;
1654*
1655* cancels monomials
1656* occuring in denominator
1657* and enumerator  ?          naNumbOfPar != 1;
1658*
1659* #defines for Factory:
1660* FACTORY_GCD_TEST: do not apply built in gcd for
1661*   univariate polynomials, always use Factory
1662*/
1663//#define FACTORY_GCD_TEST
1664void naNormalize(number &pp)
1665{
1666
1667  //naTest(pp); // input may not be "normal"
1668  lnumber p = (lnumber)pp;
1669
1670  if ((p==NULL) /*|| (p->s==2)*/)
1671    return;
1672  p->s = 2;
1673  napoly x = p->z;
1674  napoly y = p->n;
1675  if ((y!=NULL) && (naMinimalPoly!=NULL))
1676  {
1677    y = napInvers(y, naMinimalPoly);
1678    x = napMult(x, y);
1679    if (napGetExp(x,1) >= napGetExp(naMinimalPoly,1))
1680      x = napRemainder(x, naMinimalPoly);
1681    p->z = x;
1682    p->n = y = NULL;
1683  }
1684  /* check for degree of x too high: */
1685  if ((x!=NULL) && (naMinimalPoly!=NULL) && (x!=naMinimalPoly)
1686  && (napGetExp(x,1)>napGetExp(naMinimalPoly,1)))
1687  // DO NOT REDUCE naMinimalPoly with itself
1688  {
1689    x = napRemainder(x, naMinimalPoly);
1690    p->z = x;
1691  }
1692  /* normalize all coefficients in n and z (if in Q) */
1693  if (naIsChar0)
1694  {
1695    while(x!=NULL)
1696    {
1697      nacNormalize(napGetCoeff(x));
1698      napIter(x);
1699    }
1700    x = p->z;
1701  }
1702  if (y==NULL) return;
1703  if (naIsChar0)
1704  {
1705    while(y!=NULL)
1706    {
1707      nacNormalize(napGetCoeff(y));
1708      napIter(y);
1709    }
1710    y = p->n;
1711  // p->n !=NULL:
1712  /* collect all denoms from y and multiply x and y by it */
1713    number n=napLcm(y);
1714    napMultN(x,n);
1715    napMultN(y,n);
1716    nacDelete(&n,nacRing);
1717    while(x!=NULL)
1718    {
1719      nacNormalize(napGetCoeff(x));
1720      napIter(x);
1721    }
1722    x = p->z;
1723    while(y!=NULL)
1724    {
1725      nacNormalize(napGetCoeff(y));
1726      napIter(y);
1727    }
1728    y = p->n;
1729  }
1730  if ((naMinimalPoly == NULL) && (x!=NULL) && (y!=NULL))
1731  {
1732    int i;
1733    for (i=naNumbOfPar-1; i>=0; i--)
1734    {
1735      napoly xx=x;
1736      napoly yy=y;
1737      int m = napExpi(i, yy, xx);
1738      if (m != 0)          // in this case xx!=NULL!=yy
1739      {
1740        while (xx != NULL)
1741        {
1742          napAddExp(xx,i+1, -m);
1743          napIter(xx);
1744        }
1745        while (yy != NULL)
1746        {
1747          napAddExp(yy,i+1, -m);
1748          napIter(yy);
1749        }
1750      }
1751    }
1752  }
1753  if (napIsConstant(y)) /* i.e. => simplify to (1/c)*z / monom */
1754  {
1755    if (nacIsOne(napGetCoeff(y)))
1756    {
1757      napDelete1(&y);
1758      p->n = NULL;
1759      naTest(pp);
1760      return;
1761    }
1762    number h1 = nacInvers(napGetCoeff(y));
1763    nacNormalize(h1);
1764    napMultN(x, h1);
1765    nacDelete(&h1,nacRing);
1766    napDelete1(&y);
1767    p->n = NULL;
1768    naTest(pp);
1769    return;
1770  }
1771#ifndef FACTORY_GCD_TEST
1772  if (naNumbOfPar == 1) /* apply built-in gcd */
1773  {
1774    napoly x1,y1;
1775    if (napGetExp(x,1) >= napGetExp(y,1))
1776    {
1777      x1 = napCopy(x);
1778      y1 = napCopy(y);
1779    }
1780    else
1781    {
1782      x1 = napCopy(y);
1783      y1 = napCopy(x);
1784    }
1785    napoly r;
1786    loop
1787    {
1788      r = napRemainder(x1, y1);
1789      if ((r==NULL) || (napNext(r)==NULL)) break;
1790      x1 = y1;
1791      y1 = r;
1792    }
1793    if (r!=NULL)
1794    {
1795      napDelete(&r);
1796      napDelete(&y1);
1797    }
1798    else
1799    {
1800      napDivMod(x, y1, &(p->z), &r);
1801      napDivMod(y, y1, &(p->n), &r);
1802      napDelete(&y1);
1803    }
1804    x = p->z;
1805    y = p->n;
1806    /* collect all denoms from y and multiply x and y by it */
1807    if (naIsChar0)
1808    {
1809      number n=napLcm(y);
1810      napMultN(x,n);
1811      napMultN(y,n);
1812      nacDelete(&n,nacRing);
1813      while(x!=NULL)
1814      {
1815        nacNormalize(napGetCoeff(x));
1816        napIter(x);
1817      }
1818      x = p->z;
1819      while(y!=NULL)
1820      {
1821        nacNormalize(napGetCoeff(y));
1822        napIter(y);
1823      }
1824      y = p->n;
1825    }
1826    if (napNext(y)==NULL)
1827    {
1828      if (nacIsOne(napGetCoeff(y)))
1829      {
1830        if (napGetExp(y,1)==0)
1831        {
1832          napDelete1(&y);
1833          p->n = NULL;
1834        }
1835        naTest(pp);
1836        return;
1837      }
1838    }
1839  }
1840#endif /* FACTORY_GCD_TEST */
1841#ifdef HAVE_FACTORY
1842#ifndef FACTORY_GCD_TEST
1843  else
1844#endif
1845  {
1846    napoly xx,yy;
1847    singclap_algdividecontent(x,y,xx,yy);
1848    if (xx!=NULL)
1849    {
1850      p->z=xx;
1851      p->n=yy;
1852      napDelete(&x);
1853      napDelete(&y);
1854    }
1855  }
1856#endif
1857  /* remove common factors from z and n */
1858  x=p->z;
1859  y=p->n;
1860  if(!nacGreaterZero(napGetCoeff(y)))
1861  {
1862    x=napNeg(x);
1863    y=napNeg(y);
1864  }
1865  number g=nacCopy(napGetCoeff(x));
1866  napIter(x);
1867  while (x!=NULL)
1868  {
1869    number d=nacGcd(g,napGetCoeff(x), nacRing);
1870    if(nacIsOne(d))
1871    {
1872      nacDelete(&g,nacRing);
1873      nacDelete(&d,nacRing);
1874      naTest(pp);
1875      return;
1876    }
1877    nacDelete(&g,nacRing);
1878    g = d;
1879    napIter(x);
1880  }
1881  while (y!=NULL)
1882  {
1883    number d=nacGcd(g,napGetCoeff(y), nacRing);
1884    if(nacIsOne(d))
1885    {
1886      nacDelete(&g,nacRing);
1887      nacDelete(&d,nacRing);
1888      naTest(pp);
1889      return;
1890    }
1891    nacDelete(&g,nacRing);
1892    g = d;
1893    napIter(y);
1894  }
1895  x=p->z;
1896  y=p->n;
1897  while (x!=NULL)
1898  {
1899    number d = nacIntDiv(napGetCoeff(x),g);
1900    napSetCoeff(x,d);
1901    napIter(x);
1902  }
1903  while (y!=NULL)
1904  {
1905    number d = nacIntDiv(napGetCoeff(y),g);
1906    napSetCoeff(y,d);
1907    napIter(y);
1908  }
1909  nacDelete(&g,nacRing);
1910  naTest(pp);
1911}
1912
1913/*2
1914* returns in result->n 1
1915* and in     result->z the lcm(a->z,b->n)
1916*/
1917number naLcm(number la, number lb, const ring r)
1918{
1919  lnumber result;
1920  lnumber a = (lnumber)la;
1921  lnumber b = (lnumber)lb;
1922  result = (lnumber)omAlloc0Bin(rnumber_bin);
1923  //if (((naMinimalPoly==NULL) && (naI==NULL)) || !naIsChar0)
1924  //{
1925  //  result->z = napInit(1);
1926  //  return (number)result;
1927  //}
1928  naNormalize(lb);
1929  naTest(la);
1930  naTest(lb);
1931  napoly x = napCopy(a->z);
1932  number t = napLcm(b->z); // get all denom of b->z
1933  if (!nacIsOne(t))
1934  {
1935    number bt, r;
1936    napoly xx=x;
1937    while (xx!=NULL)
1938    {
1939      bt = nacGcd(t, napGetCoeff(xx), nacRing);
1940      r = nacMult(t, napGetCoeff(xx));
1941      nacDelete(&napGetCoeff(xx),nacRing);
1942      napGetCoeff(xx) = nacDiv(r, bt);
1943      nacNormalize(napGetCoeff(xx));
1944      nacDelete(&bt,nacRing);
1945      nacDelete(&r,nacRing);
1946      napIter(xx);
1947    }
1948  }
1949  nacDelete(&t,nacRing);
1950  result->z = x;
1951#ifdef HAVE_FACTORY
1952  if (b->n!=NULL)
1953  {
1954    result->z=singclap_alglcm(result->z,b->n);
1955    napDelete(&x);
1956  }
1957#endif
1958  naTest(la);
1959  naTest(lb);
1960  naTest((number)result);
1961  return ((number)result);
1962}
1963
1964/*2
1965* input: a set of constant polynomials
1966* sets the global variable naI
1967*/
1968void naSetIdeal(ideal I)
1969{
1970  int i;
1971
1972  if (idIs0(I))
1973  {
1974    for (i=naI->anz-1; i>=0; i--)
1975      napDelete(&naI->liste[i]);
1976    omFreeBin((ADDRESS)naI, snaIdeal_bin);
1977    naI=NULL;
1978  }
1979  else
1980  {
1981    lnumber h;
1982    number a;
1983    napoly x;
1984
1985    naI=(naIdeal)omAllocBin(snaIdeal_bin);
1986    naI->anz=IDELEMS(I);
1987    naI->liste=(napoly*)omAlloc(naI->anz*sizeof(napoly));
1988    for (i=IDELEMS(I)-1; i>=0; i--)
1989    {
1990      h=(lnumber)pGetCoeff(I->m[i]);
1991      /* We only need the enumerator of h, as we expect it to be a polynomial */
1992      naI->liste[i]=napCopy(h->z);
1993      /* If it isn't normalized (lc = 1) do this */
1994      if (!nacIsOne(napGetCoeff(naI->liste[i])))
1995      {
1996        x=naI->liste[i];
1997        nacNormalize(napGetCoeff(x));
1998        a=nacCopy(napGetCoeff(x));
1999        number aa=nacInvers(a);
2000        nacDelete(&a,nacRing);
2001        napMultN(x,aa);
2002        nacDelete(&aa,nacRing);
2003      }
2004    }
2005  }
2006}
2007
2008/*2
2009* map Z/p -> Q(a)
2010*/
2011number naMapP0(number c)
2012{
2013  if (npIsZero(c)) return NULL;
2014  lnumber l=(lnumber)omAllocBin(rnumber_bin);
2015  l->s=2;
2016  l->z=(napoly)p_Init(nacRing);
2017  int i=(int)((long)c);
2018  if (i>(naPrimeM>>2)) i-=naPrimeM;
2019  napGetCoeff(l->z)=nlInit(i);
2020  l->n=NULL;
2021  return (number)l;
2022}
2023
2024/*2
2025* map Q -> Q(a)
2026*/
2027number naMap00(number c)
2028{
2029  if (nlIsZero(c)) return NULL;
2030  lnumber l=(lnumber)omAllocBin(rnumber_bin);
2031  l->s=0;
2032  l->z=(napoly)p_Init(nacRing);
2033  napGetCoeff(l->z)=nlCopy(c);
2034  l->n=NULL;
2035  return (number)l;
2036}
2037
2038/*2
2039* map Z/p -> Z/p(a)
2040*/
2041number naMapPP(number c)
2042{
2043  if (npIsZero(c)) return NULL;
2044  lnumber l=(lnumber)omAllocBin(rnumber_bin);
2045  l->s=2;
2046  l->z=(napoly)p_Init(nacRing);
2047  napGetCoeff(l->z)=c; /* omit npCopy, because npCopy is a no-op */
2048  l->n=NULL;
2049  return (number)l;
2050}
2051
2052/*2
2053* map Z/p' -> Z/p(a)
2054*/
2055number naMapPP1(number c)
2056{
2057  if (npIsZero(c)) return NULL;
2058  int i=(int)((long)c);
2059  if (i>naPrimeM) i-=naPrimeM;
2060  number n=npInit(i);
2061  if (npIsZero(n)) return NULL;
2062  lnumber l=(lnumber)omAllocBin(rnumber_bin);
2063  l->s=2;
2064  l->z=(napoly)p_Init(nacRing);
2065  napGetCoeff(l->z)=n;
2066  l->n=NULL;
2067  return (number)l;
2068}
2069
2070/*2
2071* map Q -> Z/p(a)
2072*/
2073number naMap0P(number c)
2074{
2075  if (nlIsZero(c)) return NULL;
2076  number n=npInit(nlModP(c,npPrimeM));
2077  if (npIsZero(n)) return NULL;
2078  npTest(n);
2079  lnumber l=(lnumber)omAllocBin(rnumber_bin);
2080  l->s=2;
2081  l->z=(napoly)p_Init(nacRing);
2082  napGetCoeff(l->z)=n;
2083  l->n=NULL;
2084  return (number)l;
2085}
2086
2087static number (*nacMap)(number);
2088static int naParsToCopy;
2089static ring napMapRing;
2090static napoly napMap(napoly p)
2091{
2092  napoly w, a;
2093
2094  if (p==NULL) return NULL;
2095  a = w = (napoly)p_Init(nacRing);
2096  int i;
2097  for(i=1;i<=naParsToCopy;i++)
2098    napSetExp(a,i,napGetExpFrom(p,i,napMapRing));
2099  p_Setm(a,nacRing);
2100  napGetCoeff(w) = nacMap(napGetCoeff(p));
2101  loop
2102  {
2103    napIter(p);
2104    if (p==NULL) break;
2105    napNext(a) = (napoly)p_Init(nacRing);
2106    napIter(a);
2107    for(i=1;i<=naParsToCopy;i++)
2108      napSetExp(a,i,napGetExpFrom(p,i,napMapRing));
2109    p_Setm(a,nacRing);
2110    napGetCoeff(a) = nacMap(napGetCoeff(p));
2111  }
2112  napNext(a) = NULL;
2113  return w;
2114}
2115
2116static napoly napPerm(napoly p,const int *par_perm,const ring src_ring,const nMapFunc nMap)
2117{
2118  napoly w, a;
2119
2120  if (p==NULL) return NULL;
2121  w = (napoly)p_Init(nacRing);
2122  int i;
2123  BOOLEAN not_null=TRUE;
2124  loop
2125  {
2126    for(i=1;i<=rPar(src_ring);i++)
2127    {
2128      int e;
2129      if (par_perm!=NULL) e=par_perm[i-1];
2130      else                e=-i;
2131      int ee=napGetExpFrom(p,i,src_ring);
2132      if (e<0)
2133        napSetExp(w,-e,ee);
2134      else if (ee>0)
2135        not_null=FALSE;
2136    }
2137    napGetCoeff(w) = nMap(napGetCoeff(p));
2138    p_Setm(w,nacRing);
2139    napIter(p);
2140    if (!not_null)
2141    {
2142      if (p==NULL)
2143      {
2144        p_Delete(&w,nacRing);
2145        return NULL;
2146      }
2147      /* else continue*/
2148      nacDelete(&(napGetCoeff(w)),nacRing);
2149    }
2150    else
2151    {
2152      if (p==NULL) return w;
2153      else
2154      {
2155        napNext(w)=napPerm(p,par_perm,src_ring,nMap);
2156        return w;
2157      }
2158    }
2159  }
2160}
2161
2162/*2
2163* map _(a) -> _(b)
2164*/
2165number naMapQaQb(number c)
2166{
2167  if (c==NULL) return NULL;
2168  lnumber erg= (lnumber)omAlloc0Bin(rnumber_bin);
2169  lnumber src =(lnumber)c;
2170  erg->s=src->s;
2171  erg->z=napMap(src->z);
2172  erg->n=napMap(src->n);
2173  if (naMinimalPoly!=NULL)
2174  {
2175    if (napGetExp(erg->z,1) >= napGetExp(naMinimalPoly,1))
2176    {
2177      erg->z = napRemainder(erg->z, naMinimalPoly);
2178      if (erg->z==NULL)
2179      {
2180        number t_erg=(number)erg;
2181        naDelete(&t_erg,currRing);
2182        return (number)NULL;
2183      }
2184    }
2185    if (erg->n!=NULL)
2186    {
2187      if (napGetExp(erg->n,1) >= napGetExp(naMinimalPoly,1))
2188        erg->n = napRemainder(erg->n, naMinimalPoly);
2189      if ((napIsConstant(erg->n)) && nacIsOne(napGetCoeff(erg->n)))
2190        napDelete(&(erg->n));
2191    }
2192  }
2193  return (number)erg;
2194}
2195
2196nMapFunc naSetMap(ring src, ring dst)
2197{
2198  if (rField_is_Q_a(dst)) /* -> Q(a) */
2199  {
2200    if (rField_is_Q(src))
2201    {
2202      return naMap00;   /*Q -> Q(a)*/
2203    }
2204    if (rField_is_Zp(src))
2205    {
2206      naPrimeM = rChar(src);
2207      return naMapP0;  /* Z/p -> Q(a)*/
2208    }
2209    if (rField_is_Q_a(src))
2210    {
2211      int i;
2212      naParsToCopy=0;
2213      for(i=0;i<rPar(src);i++)
2214      {
2215        if ((i>=rPar(dst))
2216        ||(strcmp(src->parameter[i],dst->parameter[i])!=0))
2217           return NULL;
2218        naParsToCopy++;
2219      }
2220      napMapRing=src;
2221      nacMap=nacCopy;
2222      if ((naParsToCopy==rPar(dst))&&(naParsToCopy==rPar(src)))
2223        return naCopy;    /* Q(a) -> Q(a) */
2224      return naMapQaQb;   /* Q(a..) -> Q(a..) */
2225    }
2226  }
2227  /*-----------------------------------------------------*/
2228  if (rField_is_Zp_a(dst)) /* -> Z/p(a) */
2229  {
2230    if (rField_is_Q(src))
2231    {
2232      return naMap0P;   /*Q -> Z/p(a)*/
2233    }
2234    if (rField_is_Zp(src))
2235    {
2236      int c=rChar(src);
2237      if (c==npPrimeM)
2238      {
2239        return naMapPP;  /* Z/p -> Z/p(a)*/
2240      }
2241      else
2242      {
2243        naPrimeM = c;
2244        return naMapPP1;  /* Z/p' -> Z/p(a)*/
2245      }
2246    }
2247    if (rField_is_Zp_a(src))
2248    {
2249      if (rChar(src)==rChar(dst))
2250      {
2251        nacMap=nacCopy;
2252      }
2253      else
2254      {
2255        npMapPrime=rChar(src);
2256        nacMap = npMapP;
2257      }
2258      int i;
2259      naParsToCopy=0;
2260      for(i=0;i<rPar(src);i++)
2261      {
2262        if ((i>=rPar(dst))
2263        ||(strcmp(src->parameter[i],dst->parameter[i])!=0))
2264           return NULL;
2265        naParsToCopy++;
2266      }
2267      napMapRing=src;
2268      if ((naParsToCopy==rPar(dst))&&(naParsToCopy==rPar(src))
2269      && (nacMap==nacCopy))
2270        return naCopy;    /* Z/p(a) -> Z/p(a) */
2271      return naMapQaQb;   /* Z/p(a),Z/p'(a) -> Z/p(b)*/
2272    }
2273  }
2274  return NULL;      /* default */
2275}
2276
2277/*2
2278* convert a napoly number into a poly
2279*/
2280poly naPermNumber(number z, int * par_perm, int P, ring oldRing)
2281{
2282  if (z==NULL) return NULL;
2283  poly res=NULL;
2284  poly p;
2285  napoly za=((lnumber)z)->z;
2286  napoly zb=((lnumber)z)->n;
2287  nMapFunc nMap=naSetMap(oldRing,currRing);
2288  if (currRing->parameter!=NULL)
2289    nMap=currRing->algring->cf->cfSetMap(oldRing->algring, nacRing);
2290  else
2291    nMap=currRing->cf->cfSetMap(oldRing->algring, currRing);
2292  if (nMap==NULL) return NULL; /* emergency exit only */
2293  do
2294  {
2295    p = pInit();
2296    pNext(p)=NULL;
2297    nNew(&pGetCoeff(p));
2298    int i;
2299    for(i=pVariables;i;i--)
2300       pSetExp(p,i, 0);
2301    pSetComp(p, 0);
2302    napoly pa=NULL;
2303    lnumber pan;
2304    if (currRing->parameter!=NULL)
2305    {
2306      assume(oldRing->algring!=NULL);
2307      pGetCoeff(p)=(number)omAlloc0Bin(rnumber_bin);
2308      pan=(lnumber)pGetCoeff(p);
2309      pan->s=2;
2310      pan->z=napInitz(nMap(napGetCoeff(za)));
2311      pa=pan->z;
2312    }
2313    else
2314    {
2315      pGetCoeff(p)=nMap(napGetCoeff(za));
2316    }
2317    for(i=0;i<P;i++)
2318    {
2319      if(napGetExpFrom(za,i+1,oldRing)!=0)
2320      {
2321        if(par_perm==NULL)
2322        {
2323          if ((rPar(currRing)>=i) && (pa!=NULL))
2324          {
2325            napSetExp(pa,i+1,napGetExpFrom(za,i+1,oldRing));
2326            p_Setm(pa,nacRing);
2327          }
2328          else
2329          {
2330            pDelete(&p);
2331            break;
2332          }
2333        }
2334        else if(par_perm[i]>0)
2335          pSetExp(p,par_perm[i],napGetExpFrom(za,i+1,oldRing));
2336        else if((par_perm[i]<0)&&(pa!=NULL))
2337        {
2338          napSetExp(pa,-par_perm[i], napGetExpFrom(za,i+1,oldRing));
2339          p_Setm(pa,nacRing);
2340        }
2341        else
2342        {
2343          pDelete(&p);
2344          break;
2345        }
2346      }
2347    }
2348    if (p!=NULL)
2349    {
2350      pSetm(p);
2351      if (zb!=NULL)
2352      {
2353        if  (currRing->P>0)
2354        {
2355          pan->n=napPerm(zb,par_perm,oldRing,nMap);
2356          if(pan->n==NULL) /* error in mapping or mapping to variable */
2357            pDelete(&p);
2358        }
2359        else
2360          pDelete(&p);
2361      }
2362      pTest(p);
2363      res=pAdd(res,p);
2364    }
2365    napIter(za);
2366  }
2367  while (za!=NULL);
2368  pTest(res);
2369  return res;
2370}
2371
2372number   naGetDenom(number &n, const ring r)
2373{
2374  if (r==currRing) naNormalize(n);
2375  lnumber x=(lnumber)n;
2376  if (x->n!=NULL)
2377  {
2378    lnumber rr=(lnumber)omAlloc0Bin(rnumber_bin);
2379    rr->z=nap_Copy(naGetDenom0(x),r);
2380    rr->s = 2;
2381    return (number)rr;
2382  }
2383  return r->cf->nInit(1);
2384}
2385
2386#ifdef LDEBUG
2387BOOLEAN naDBTest(number a, char *f,int l)
2388{
2389  lnumber x=(lnumber)a;
2390  if (x == NULL)
2391    return TRUE;
2392  omCheckAddrSize(a, sizeof(snumber));
2393  napoly p = x->z;
2394  if (p==NULL)
2395  {
2396    Print("0/* in %s:%d\n",f,l);
2397    return FALSE;
2398  }
2399  while(p!=NULL)
2400  {
2401    if ((naIsChar0 && nlIsZero(napGetCoeff(p)))
2402    || ((!naIsChar0) && npIsZero(napGetCoeff(p))))
2403    {
2404      Print("coeff 0 in %s:%d\n",f,l);
2405      return FALSE;
2406    }
2407    if((naMinimalPoly!=NULL)&&(napGetExp(p,1)>napGetExp(naMinimalPoly,1))
2408    &&(p!=naMinimalPoly))
2409    {
2410      Print("deg>minpoly in %s:%d\n",f,l);
2411      return FALSE;
2412    }
2413    //if (naIsChar0 && (((int)p->ko &3) == 0) && (p->ko->s==0) && (x->s==2))
2414    //{
2415    //  Print("normalized with non-normal coeffs in %s:%d\n",f,l);
2416    //  return FALSE;
2417    //}
2418    if (naIsChar0 && !(nlDBTest(napGetCoeff(p),f,l)))
2419      return FALSE;
2420    napIter(p);
2421  }
2422  p = naGetDenom0(x);
2423  while(p!=NULL)
2424  {
2425    if (naIsChar0 && !(nlDBTest(napGetCoeff(p),f,l)))
2426      return FALSE;
2427    napIter(p);
2428  }
2429  return TRUE;
2430}
2431#endif
2432
Note: See TracBrowser for help on using the repository browser.