source: git/Singular/longalg.cc @ c8bd75

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