source: git/kernel/longalg.cc @ f1e33bb

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