source: git/Singular/longalg.cc @ a38f5ea

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