source: git/Singular/longalg.cc @ 5812c69

spielwiese
Last change on this file since 5812c69 was 5812c69, checked in by Hans Schönemann <hannes@…>, 26 years ago
cosmetic changes git-svn-id: file:///usr/local/Singular/svn/trunk@2517 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 43.3 KB
Line 
1/****************************************
2*  Computer Algebra System SINGULAR     *
3****************************************/
4/* $Id: longalg.cc,v 1.25 1998-09-24 09:59:47 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  for (i=(naNumbOfPar-1); i>=0; i--)
1020  {
1021    x->e[i] = napExpi(i,a,b);
1022  }
1023  return x;
1024}
1025
1026
1027number napLcm(alg a)
1028{
1029  number h = nacInit(1);
1030
1031  if (naIsChar0)
1032  {
1033    number d;
1034    alg b = a;
1035
1036    while (b!=NULL)
1037    {
1038      d = nacLcm(h, b->ko);
1039      nacDelete(&h);
1040      h = d;
1041      b = b->ne;
1042    }
1043  }
1044  return h;
1045}
1046
1047
1048/*2
1049* meins  (for reduction in algebraic extension)
1050* checks if head of p divides head of q
1051* doesn't delete p and q
1052*/
1053BOOLEAN napDivPoly (alg p, alg q)
1054{
1055  int j=0;   /* evtl. von naNumber.. -1 abwaerts zaehlen */
1056
1057  while (p->e[j] <= q->e[j])
1058  {
1059    j++;
1060    if (j >= naNumbOfPar)
1061      return 1;
1062  }
1063  return 0;
1064}
1065
1066
1067/*2
1068* meins  (for reduction in algebraic extension)
1069* Normalform of poly with naI
1070* changes q and returns it
1071*/
1072alg napRedp (alg q)
1073{
1074  alg h = (alg)Alloc0(napMonomSize);
1075  int i=0,j;
1076
1077  loop
1078  {
1079    if (napDivPoly (naI->liste[i], q))
1080    {
1081      mmTestP((ADDRESS)q,napMonomSize);
1082      //StringSetS("");
1083      //napWrite(q);
1084      //napWrite(naI->liste[i]);
1085      //Print(StringAppendS("\n"));
1086      /* h = lt(q)/lt(naI->liste[i])*/
1087      h->ko = nacCopy(q->ko);
1088      for (j=naNumbOfPar-1; j>=0; j--)
1089        h->e[j] = q->e[j] - naI->liste[i]->e[j];
1090      h = napMult (h, napCopy(naI->liste[i]));
1091      h = napNeg (h);
1092      q = napAdd (q, napCopy(h));
1093      napDelete (&(h->ne));
1094      if (q == NULL)
1095      {
1096        napDelete(&h);
1097        return q;
1098      }
1099      /* try to reduce further */
1100      i = 0;
1101    }
1102    else
1103    {
1104      i++;
1105      if (i >= naI->anz)
1106      {
1107        napDelete(&h);
1108        return q;
1109      }
1110    }
1111  }
1112}
1113
1114
1115/*2
1116* meins  (for reduction in algebraic extension)
1117* reduces the tail of Poly q
1118* needs q != NULL
1119* changes q and returns it
1120*/
1121alg napTailred (alg q)
1122{
1123  alg h;
1124
1125  h = q->ne;
1126  while (h != NULL)
1127  {
1128     h = napRedp (h);
1129     if (h == NULL)
1130        return q;
1131     h = h->ne;
1132  }
1133  return q;
1134}
1135
1136
1137/*================ procedure for rational functions: naXXXX =================*/
1138
1139/*2
1140*  z:= i
1141*/
1142number naInit(int i)
1143{
1144  if (i!=0)
1145  {
1146    lnumber l = (lnumber)Alloc(sizeof(rnumber));
1147    l->z = napInit(i);
1148    if (l->z==NULL)
1149    {
1150      Free((ADDRESS)l, sizeof(rnumber));
1151      return NULL;
1152    }
1153    l->s = 2;
1154    l->n = NULL;
1155    return (number)l;
1156  }
1157  /*else*/
1158  return NULL;
1159}
1160
1161number  naPar(int i)
1162{
1163  lnumber l = (lnumber)Alloc(sizeof(rnumber));
1164  l->s = 2;
1165  l->z = napInit(1);
1166  l->z->e[i-1]=1;
1167  l->n = NULL;
1168  return (number)l;
1169}
1170
1171int     naParDeg(number n)     /* i := deg(n) */
1172{
1173  lnumber l = (lnumber)n;
1174  if (l==NULL) return -1;
1175  return napDeg(l->z);
1176}
1177
1178/*2
1179* convert a number to int (if possible)
1180*/
1181int naInt(number &n)
1182{
1183  lnumber l=(lnumber)n;
1184  if ((l!=NULL)&&(l->n==NULL)&&(napDeg(l->z)==0))
1185  {
1186    return nacInt(l->z->ko);
1187  }
1188  return 0;
1189}
1190
1191/*2
1192*  deletes p
1193*/
1194#ifdef LDEBUG
1195void naDBDelete(number *p,char *f, int lno)
1196#else
1197void naDelete(number *p)
1198#endif
1199{
1200  lnumber l = (lnumber) * p;
1201  if (l==NULL) return;
1202  napDelete(&(l->z));
1203  napDelete(&(l->n));
1204#if defined(MDEBUG) && defined(LDEBUG)
1205  mmDBFreeBlock((ADDRESS)l, sizeof(rnumber),f,lno);
1206#else
1207  Free((ADDRESS)l, sizeof(rnumber));
1208#endif
1209  *p = NULL;
1210}
1211
1212/*2
1213* copy p to erg
1214*/
1215number naCopy(number p)
1216{
1217  if (p==NULL) return NULL;
1218  naTest(p);
1219  lnumber erg;
1220  lnumber src = (lnumber)p;
1221  erg = (lnumber)Alloc0(sizeof(rnumber));
1222  erg->z = napCopy(src->z);
1223  erg->n = napCopy(src->n);
1224  erg->s = src->s;
1225  return (number)erg;
1226}
1227
1228/*2
1229* a dummy number: 0
1230*/
1231void naNew(number *z)
1232{
1233  *z = NULL;
1234}
1235
1236/*2
1237*  addition; lu:= la + lb
1238*/
1239number naAdd(number la, number lb)
1240{
1241  alg x, y;
1242  lnumber lu;
1243  lnumber a = (lnumber)la;
1244  lnumber b = (lnumber)lb;
1245  if (a==NULL) return naCopy(lb);
1246  if (b==NULL) return naCopy(la);
1247  mmTestP(a,sizeof(rnumber));
1248  mmTestP(b,sizeof(rnumber));
1249  lu = (lnumber)Alloc(sizeof(rnumber));
1250  if (b->n!=NULL) x = napMult(napCopy(a->z), napCopy(b->n));
1251  else            x = napCopy(a->z);
1252  if (a->n!=NULL) y = napMult(napCopy(b->z), napCopy(a->n));
1253  else            y = napCopy(b->z);
1254  lu->z = napAdd(x, y);
1255  if (lu->z==NULL)
1256  {
1257    Free((ADDRESS)lu, sizeof(rnumber));
1258    return (number)NULL;
1259  }
1260  if (a->n!=NULL)
1261  {
1262    if (b->n!=NULL) x = napMult(napCopy(a->n), napCopy(b->n));
1263    else            x = napCopy(a->n);
1264  }
1265  else
1266  {
1267    if (b->n!=NULL) x = napCopy(b->n);
1268    else            x = NULL;
1269  }
1270  if ((x!=NULL) && (napDeg(x)==0) && nacIsOne(x->ko))
1271    napDelete(&x);
1272  lu->n = x;
1273  lu->s = 0;
1274  naTest((number)lu);
1275  return (number)lu;
1276}
1277
1278/*2
1279*  subtraction; r:= la - lb
1280*/
1281number naSub(number la, number lb)
1282{
1283  lnumber lu;
1284
1285  if (lb==NULL) return naCopy(la);
1286  if (la==NULL)
1287  {
1288    //if (lb!=NULL)
1289    //{
1290      lu = (lnumber)naCopy(lb);
1291      lu->z = napNeg(lu->z);
1292      return (number)lu;
1293    //}
1294    //else
1295    //  return NULL;
1296  }
1297
1298  alg x, y;
1299  lnumber a = (lnumber)la;
1300  lnumber b = (lnumber)lb;
1301
1302  mmTestP(a,sizeof(rnumber));
1303  mmTestP(b,sizeof(rnumber));
1304  lu = (lnumber)Alloc(sizeof(rnumber));
1305  if (b->n!=NULL) x = napMult(napCopy(a->z), napCopy(b->n));
1306  else            x = napCopy(a->z);
1307  if (a->n!=NULL) y = napMult(napCopy(b->z), napCopyNeg(a->n));
1308  else            y = napCopyNeg(b->z);
1309  lu->z = napAdd(x, y);
1310  if (lu->z==NULL)
1311  {
1312    Free((ADDRESS)lu, sizeof(rnumber));
1313    return (number)NULL;
1314  }
1315  if (a->n!=NULL)
1316  {
1317    if (b->n!=NULL) x = napMult(napCopy(a->n), napCopy(b->n));
1318    else            x = napCopy(a->n);
1319  }
1320  else
1321  {
1322    if (b->n!=NULL) x = napCopy(b->n);
1323    else            x = NULL;
1324  }
1325  if ((x!=NULL)&& (napDeg(x)==0) && nacIsOne(x->ko))
1326    napDelete(&x);
1327  lu->n = x;
1328  lu->s = 0;
1329  naTest((number)lu);
1330  return (number)lu;
1331}
1332
1333/*2
1334*  multiplication; r:= la * lb
1335*/
1336number naMult(number la, number lb)
1337{
1338  if ((la==NULL) || (lb==NULL))
1339    return NULL;
1340
1341  lnumber a = (lnumber)la;
1342  lnumber b = (lnumber)lb;
1343  lnumber lo;
1344  alg x;
1345
1346  mmTestP(a,sizeof(rnumber));
1347  mmTestP(b,sizeof(rnumber));
1348  naTest(la);
1349  naTest(lb);
1350
1351  lo = (lnumber)Alloc(sizeof(rnumber));
1352  lo->z = napMult(napCopy(a->z), napCopy(b->z));
1353
1354  if (a->n==NULL)
1355  {
1356    if (b->n==NULL)
1357      x = NULL;
1358    else
1359      x = napCopy(b->n);
1360  }
1361  else
1362  {
1363    if (b->n==NULL)
1364    {
1365      x = napCopy(a->n);
1366    }
1367    else
1368    {
1369      x = napMult(napCopy(b->n), napCopy(a->n));
1370    }
1371  }
1372  if (naMinimalPoly!=NULL)
1373  {
1374    if (lo->z->e[0] >= naMinimalPoly->e[0])
1375      lo->z = napRemainder(lo->z, naMinimalPoly);
1376    if ((x!=NULL) && (x->e[0] >= naMinimalPoly->e[0]))
1377      x = napRemainder(x, naMinimalPoly);
1378  }
1379#if FEHLER1
1380  if (naI!=NULL)
1381  {
1382    lo->z = napRedp (lo->z);
1383    if (lo->z != NULL)
1384       lo->z = napTailred (lo->z);
1385    if (x!=NULL)
1386    {
1387      x = napRedp (x);
1388      if (x!=NULL)
1389        x = napTailred (x);
1390    }
1391  }
1392#endif
1393  if ((x!=NULL) && (napDeg(x)==0) && nacIsOne(x->ko))
1394    napDelete(&x);
1395  lo->n = x;
1396  lo->s = 0;
1397  if(lo->z==NULL)
1398  {
1399    Free((ADDRESS)lo,sizeof(rnumber));
1400    lo=NULL;
1401  }
1402  naTest((number)lo);
1403  return (number)lo;
1404}
1405
1406number naIntDiv(number la, number lb)
1407{
1408  lnumber res;
1409  lnumber a = (lnumber)la;
1410  lnumber b = (lnumber)lb;
1411  if ((a==NULL) || (a->z==NULL))
1412    return NULL;
1413  if ((b==NULL) || (b->z==NULL))
1414  {
1415    WerrorS("div. by 0");
1416    return NULL;
1417  }
1418  res = (lnumber)Alloc(sizeof(rnumber));
1419  res->z = napCopy(a->z);
1420  res->n = napCopy(b->z);
1421  res->s = 0;
1422  number nres=(number)res;
1423  naNormalize(nres);
1424
1425  //napDelete(&res->n);
1426  naTest(nres);
1427  return nres;
1428}
1429
1430/*2
1431*  division; lo:= la / lb
1432*/
1433number naDiv(number la, number lb)
1434{
1435  lnumber lo;
1436  lnumber a = (lnumber)la;
1437  lnumber b = (lnumber)lb;
1438  alg x;
1439
1440  if ((a==NULL) || (a->z==NULL))
1441    return NULL;
1442
1443  if ((b==NULL) || (b->z==NULL))
1444  {
1445    WerrorS("div. by 0");
1446    return NULL;
1447  }
1448  mmTestP(a,sizeof(rnumber));
1449  mmTestP(b,sizeof(rnumber));
1450  lo = (lnumber)Alloc(sizeof(rnumber));
1451  if (b->n!=NULL)
1452    lo->z = napMult(napCopy(a->z), napCopy(b->n));
1453  else
1454    lo->z = napCopy(a->z);
1455  if (a->n!=NULL)
1456    x = napMult(napCopy(b->z), napCopy(a->n));
1457  else
1458    x = napCopy(b->z);
1459  if (naMinimalPoly!=NULL)
1460  {
1461    if (lo->z->e[0] >= naMinimalPoly->e[0])
1462      lo->z = napRemainder(lo->z, naMinimalPoly);
1463    if (x->e[0] >= naMinimalPoly->e[0])
1464      x = napRemainder(x, naMinimalPoly);
1465  }
1466#if FEHLER1
1467  if (naI!=NULL)
1468  {
1469    lo->z = napRedp (lo->z);
1470    if (lo->z != NULL)
1471       lo->z = napTailred (lo->z);
1472    if (x!=NULL)
1473    {
1474      x = napRedp (x);
1475      if (x!=NULL)
1476        x = napTailred (x);
1477    }
1478  }
1479#endif
1480  if ((napDeg(x)==0) && nacIsOne(x->ko))
1481    napDelete(&x);
1482  lo->s = 0;
1483  lo->n = x;
1484  naTest((number)lo);
1485  return (number)lo;
1486}
1487
1488/*2
1489*  za:= - za
1490*/
1491number naNeg(number za)
1492{
1493  if (za!=NULL)
1494  {
1495    lnumber e = (lnumber)za;
1496    naTest(za);
1497    e->z = napNeg(e->z);
1498  }
1499  return za;
1500}
1501
1502/*2
1503* 1/a
1504*/
1505number naInvers(number a)
1506{
1507  lnumber lo;
1508  lnumber b = (lnumber)a;
1509  alg x;
1510
1511  if (b==NULL)
1512  {
1513    WerrorS("div. by 0");
1514    return NULL;
1515  }
1516  mmTestP(b,sizeof(rnumber));
1517  lo = (lnumber)Alloc0(sizeof(rnumber));
1518  lo->s = b->s;
1519  if (b->n!=NULL)
1520    lo->z = napCopy(b->n);
1521  else
1522    lo->z = napInit(1);
1523  x = b->z;
1524  if ((napDeg(x)!=0) || !nacIsOne(x->ko))
1525    x = napCopy(x);
1526  else
1527  {
1528    lo->n = NULL;
1529    naTest((number)lo);
1530    return (number)lo;
1531  }
1532  if (naMinimalPoly!=NULL)
1533  {
1534    x = napInvers(x, naMinimalPoly);
1535    x = napMult(x, lo->z);
1536    if (x->e[0] >= naMinimalPoly->e[0])
1537      x = napRemainder(x, naMinimalPoly);
1538    lo->z = x;
1539    lo->n = NULL;
1540    lo->s = 2;
1541    while (x!=NULL)
1542    {
1543      nacNormalize(x->ko);
1544      x = x->ne;
1545    }
1546  }
1547  else
1548    lo->n = x;
1549  naTest((number)lo);
1550  return (number)lo;
1551}
1552
1553
1554BOOLEAN naIsZero(number za)
1555{
1556  lnumber zb = (lnumber)za;
1557  naTest(za);
1558#ifdef TEST
1559  if ((zb!=NULL) && (zb->z==NULL)) WerrorS("internal zero error(2)");
1560#endif
1561  return ((zb==NULL) || (zb->z==NULL));
1562}
1563
1564
1565BOOLEAN naGreaterZero(number za)
1566{
1567  lnumber zb = (lnumber)za;
1568#ifdef TEST
1569  if ((zb!=NULL) && (zb->z==NULL)) WerrorS("internal zero error(3)");
1570#endif
1571  naTest(za);
1572  return ((zb!=NULL) && (zb->z!=NULL)) && (!naIsMOne(za));
1573}
1574
1575
1576/*2
1577* a = b ?
1578*/
1579BOOLEAN naEqual (number a, number b)
1580{
1581  number h;
1582  BOOLEAN bo;
1583  h = naSub(a, b);
1584  bo = naIsZero(h);
1585  naDelete(&h);
1586  return bo;
1587}
1588
1589
1590BOOLEAN naGreater (number a, number b)
1591{
1592  if (naIsZero(a))
1593    return FALSE;
1594  if (naIsZero(b))
1595    return TRUE; /* a!= 0)*/
1596  return napDeg(((lnumber)a)->z)>napDeg(((lnumber)b)->z);
1597}
1598
1599/*2
1600* reads a number
1601*/
1602char  *naRead(char *s, number *p)
1603{
1604  alg x;
1605  lnumber a;
1606  s = napRead(s, &x);
1607  if (x==NULL)
1608  {
1609    *p = NULL;
1610    return s;
1611  }
1612  *p = (number)Alloc0(sizeof(rnumber));
1613  a = (lnumber)*p;
1614  if ((naMinimalPoly!=NULL) && (x->e[0] >= naMinimalPoly->e[0]))
1615    a->z = napRemainder(x, naMinimalPoly);
1616#if FEHLER3
1617  else if (naI!=NULL)
1618  {
1619    a->z = napRedp(x);
1620    if (a->z != NULL)
1621      a->z = napTailred (a->z);
1622  }
1623#endif
1624  else
1625    a->z = x;
1626  if(a->z==NULL)
1627  {
1628    Free((ADDRESS)*p,sizeof(rnumber));
1629    *p=NULL;
1630  }
1631  else
1632  {
1633    a->n = NULL;
1634    a->s = 0;
1635    naTest(*p);
1636  }
1637  return s;
1638}
1639
1640/*2
1641* tries to convert a number to a name
1642*/
1643char * naName(number n)
1644{
1645  lnumber ph = (lnumber)n;
1646  if ((ph==NULL)||(ph->z==NULL))
1647    return NULL;
1648  int i;
1649  char *s=(char *)AllocL(4* naNumbOfPar);
1650  char *t=(char *)Alloc(8);
1651  s[0]='\0';
1652  for (i = 0; i <= naNumbOfPar - 1; i++)
1653  {
1654    if (ph->z->e[i] > 0)
1655    {
1656      if (ph->z->e[i] >1)
1657      {
1658        sprintf(t,"%s%d",naParNames[i],ph->z->e[i]);
1659        strcat(s,t);
1660      }
1661      else
1662      {
1663        strcat(s,naParNames[i]);
1664      }
1665    }
1666  }
1667  Free((ADDRESS)t,8);
1668  if (s[0]=='\0')
1669  {
1670    FreeL((ADDRESS)s);
1671    return NULL;
1672  }
1673  return s;
1674}
1675
1676/*2
1677*  writes a number
1678*/
1679void naWrite(number &phn)
1680{
1681  lnumber ph = (lnumber)phn;
1682  if ((ph==NULL)||(ph->z==NULL))
1683    StringAppendS("0");
1684  else
1685  {
1686    phn->s = 0;
1687    naNormalize(phn);
1688    napWrite(ph->z);
1689    if (ph->n!=NULL)
1690    {
1691      StringAppendS("/");
1692      napWrite(ph->n);
1693    }
1694  }
1695}
1696
1697/*2
1698* za == 1 ?
1699*/
1700BOOLEAN naIsOne(number za)
1701{
1702  lnumber a = (lnumber)za;
1703  alg x, y;
1704  number t;
1705  if (a==NULL) return FALSE;
1706  mmTestP(a,sizeof(rnumber));
1707#ifdef TEST
1708  if (a->z==NULL) WerrorS("internal zero error(4)");
1709#endif
1710  if (a->n==NULL)
1711  {
1712    if (napDeg(a->z)==0) return nacIsOne(a->z->ko);
1713    else                 return FALSE;
1714  }
1715  x = a->z;
1716  y = a->n;
1717  do
1718  {
1719    if (napComp(x, y))
1720      return FALSE;
1721    else
1722    {
1723      t = nacSub(x->ko, y->ko);
1724      if (!nacIsZero(t))
1725      {
1726        nacDelete(&t);
1727        return FALSE;
1728      }
1729      else
1730        nacDelete(&t);
1731    }
1732    x = x->ne;
1733    y = y->ne;
1734  }
1735  while ((x!=NULL) && (y!=NULL));
1736  if ((x!=NULL) || (y!=NULL)) return FALSE;
1737  napDelete(&a->z);
1738  napDelete(&a->n);
1739  a->z = napInit(1);
1740  a->n = NULL;
1741  a->s = 2;
1742  return TRUE;
1743}
1744
1745/*2
1746* za == -1 ?
1747*/
1748BOOLEAN naIsMOne(number za)
1749{
1750  lnumber a = (lnumber)za;
1751  alg x, y;
1752  number t;
1753  if (a==NULL) return FALSE;
1754  mmTestP(a,sizeof(rnumber));
1755#ifdef TEST
1756  if (a->z==NULL)
1757  {
1758    WerrorS("internal zero error(5)");
1759    return FALSE;
1760  }
1761#endif
1762  if (a->n==NULL)
1763  {
1764    if (napDeg(a->z)==0) return nacIsMOne(a->z->ko);
1765    /*else                 return FALSE;*/
1766  }
1767  return FALSE;
1768}
1769
1770/*2
1771* returns the i-th power of p (i>=0)
1772*/
1773void naPower(number p, int i, number *rc)
1774{
1775  number x;
1776  *rc = naInit(1);
1777  for (; i > 0; i--)
1778  {
1779    x = naMult(*rc, p);
1780    naDelete(rc);
1781    *rc = x;
1782  }
1783}
1784
1785/*2
1786* result =gcd(a,b)
1787*/
1788number naGcd(number a, number b)
1789{
1790  lnumber x, y;
1791  lnumber result = (lnumber)Alloc0(sizeof(rnumber));
1792
1793  x = (lnumber)a;
1794  y = (lnumber)b;
1795  if (naNumbOfPar == 1)
1796  {
1797    if (naMinimalPoly!=NULL)
1798    {
1799      if (x->z->ne!=NULL)
1800        result->z = napCopy(x->z);
1801      else
1802        result->z = napGcd0(x->z, y->z);
1803    }
1804    else
1805      result->z = napGcd(x->z, y->z);
1806  }
1807  else
1808    result->z = napGcd(x->z, y->z); // change frpm napGcd0
1809  naTest((number)result);
1810  return (number)result;
1811}
1812
1813/*2
1814* naNumbOfPar = 1:
1815* clears denominator         algebraic case;
1816* tries to simplify ratio    transcendental case;
1817*
1818* cancels monomials
1819* occuring in denominator
1820* and enumerator  ?          naNumbOfPar != 1;
1821*
1822* #defines for Factory:
1823* FACTORY_GCD_TEST: do not apply built in gcd for
1824*   univariate polynomials, always use Factory
1825*/
1826void naNormalize(number &pp)
1827{
1828
1829  naTest(pp);
1830  lnumber p = (lnumber)pp;
1831
1832  if ((p==NULL) /*|| (p->s==2)*/)
1833    return;
1834  p->s = 2;
1835  alg x = p->z;
1836  alg y = p->n;
1837  if ((y!=NULL) && (naMinimalPoly!=NULL))
1838  {
1839    y = napInvers(y, naMinimalPoly);
1840    x = napMult(x, y);
1841    if (x->e[0] >= naMinimalPoly->e[0])
1842    x = napRemainder(x, naMinimalPoly);
1843    p->z = x;
1844    p->n = y = NULL;
1845  }
1846  /* normalize all coefficients in n and z (if in Q) */
1847  if (naIsChar0)
1848  {
1849    while(x!=NULL)
1850    {
1851      nacNormalize(x->ko);
1852      x=x->ne;
1853    }
1854    x = p->z;
1855  }
1856  if (y==NULL) return;
1857  if (naIsChar0)
1858  {
1859    while(y!=NULL)
1860    {
1861      nacNormalize(y->ko);
1862      y=y->ne;
1863    }
1864    y = p->n;
1865  }
1866  // p->n !=NULL:
1867  /* collect all denoms from y and multiply x and y by it */
1868  if (naIsChar0)
1869  {
1870    number n=napLcm(y);
1871    napMultN(x,n);
1872    napMultN(y,n);
1873    nacDelete(&n);
1874    while(x!=NULL)
1875    {
1876      nacNormalize(x->ko);
1877      x=x->ne;
1878    }
1879    x = p->z;
1880    while(y!=NULL)
1881    {
1882      nacNormalize(y->ko);
1883      y=y->ne;
1884    }
1885    y = p->n;
1886  }
1887#if FEHLER1
1888  if (naMinimalPoly == NULL)
1889  {
1890    alg xx=x;
1891    alg yy=y;
1892    int i;
1893    for (i=naNumbOfPar-1; i>=0; i--)
1894    {
1895      int m = napExpi(i, yy, xx);
1896      if (m != 0)          // in this case xx!=NULL!=yy
1897      {
1898        while (xx != NULL)
1899        {
1900           xx->e[i] -= m;
1901           xx = xx->ne;
1902        }
1903        while (yy != NULL)
1904        {
1905          yy->e[i] -= m;
1906          yy = yy->ne;
1907        }
1908      }
1909    }
1910  }
1911#endif
1912  if (napDeg(y)==0) /* i.e. y=const => simplify to (1/c)*z / monom */
1913  {
1914    if (nacIsOne(y->ko))
1915    {
1916      napDelete1(&y);
1917      p->n = NULL;
1918      return;
1919    }
1920    number h1 = nacInvers(y->ko);
1921    nacNormalize(h1);
1922    napMultN(x, h1);
1923    nacDelete(&h1);
1924    napDelete1(&y);
1925    p->n = NULL;
1926    return;
1927  }
1928#ifndef FACTORY_GCD_TEST
1929  if (naNumbOfPar == 1) /* apply built-in gcd */
1930  {
1931    alg x1,y1;
1932    if (x->e[0] >= y->e[0])
1933    {
1934      x1 = napCopy(x);
1935      y1 = napCopy(y);
1936    }
1937    else
1938    {
1939      x1 = napCopy(y);
1940      y1 = napCopy(x);
1941    }
1942    alg r;
1943    loop
1944    {
1945      r = napRemainder(x1, y1);
1946      if ((r==NULL) || (r->ne==NULL)) break;
1947      x1 = y1;
1948      y1 = r;
1949    }
1950    if (r!=NULL)
1951    {
1952      napDelete(&r);
1953      napDelete(&y1);
1954    }
1955    else
1956    {
1957      napDivMod(x, y1, &(p->z), &r);
1958      napDivMod(y, y1, &(p->n), &r);
1959      napDelete(&y1);
1960    }
1961    x = p->z;
1962    y = p->n;
1963    /* collect all denoms from y and multiply x and y by it */
1964    if (naIsChar0)
1965    {
1966      number n=napLcm(y);
1967      napMultN(x,n);
1968      napMultN(y,n);
1969      nacDelete(&n);
1970      while(x!=NULL)
1971      {
1972        nacNormalize(x->ko);
1973        x=x->ne;
1974      }
1975      x = p->z;
1976      while(y!=NULL)
1977      {
1978        nacNormalize(y->ko);
1979        y=y->ne;
1980      }
1981      y = p->n;
1982    }
1983    if (y->ne==NULL)
1984    {
1985      if (nacIsOne(y->ko))
1986      {
1987        if (y->e[0]==0)
1988        {
1989          napDelete1(&y);
1990          p->n = NULL;
1991        }
1992        return;
1993      }
1994    }
1995  }
1996#endif /* FACTORY_GCD_TEST */
1997#ifdef HAVE_FACTORY
1998#ifndef FACTORY_GCD_TEST
1999  else
2000#endif
2001  {
2002    alg xx,yy;
2003    singclap_algdividecontent(x,y,xx,yy);
2004    if (xx!=NULL)
2005    {
2006      p->z=xx;
2007      p->n=yy;
2008      napDelete(&x);
2009      napDelete(&y);
2010    }
2011  }
2012#endif
2013  /* remove common factors from z and n */
2014  x=p->z;
2015  y=p->n;
2016  if(!nacGreaterZero(napGetCoeff(y)))
2017  {
2018    x=napNeg(x);
2019    y=napNeg(y);
2020  }
2021  number g=nacCopy(napGetCoeff(x));
2022  napIter(x);
2023  while (x!=NULL)
2024  {
2025    number d=nacGcd(g,napGetCoeff(x));
2026    if(nacIsOne(d))
2027    {
2028      nacDelete(&g);
2029      nacDelete(&d);
2030      return;
2031    }
2032    nacDelete(&g);
2033    g = d;
2034    napIter(x);
2035  }
2036  while (y!=NULL)
2037  {
2038    number d=nacGcd(g,napGetCoeff(y));
2039    if(nacIsOne(d))
2040    {
2041      nacDelete(&g);
2042      nacDelete(&d);
2043      return;
2044    }
2045    nacDelete(&g);
2046    g = d;
2047    napIter(y);
2048  }
2049  x=p->z;
2050  y=p->n;
2051  while (x!=NULL)
2052  {
2053    number d = nacIntDiv(napGetCoeff(x),g);
2054    napSetCoeff(x,d);
2055    napIter(x);
2056  }
2057  while (y!=NULL)
2058  {
2059    number d = nacIntDiv(napGetCoeff(y),g);
2060    napSetCoeff(y,d);
2061    napIter(y);
2062  }
2063  nacDelete(&g);
2064}
2065
2066/*2
2067* returns in result->n 1
2068* and in     result->z the lcm(a->z,b->n)
2069*/
2070number naLcm(number la, number lb)
2071{
2072  lnumber result;
2073  lnumber a = (lnumber)la;
2074  lnumber b = (lnumber)lb;
2075  result = (lnumber)Alloc0(sizeof(rnumber));
2076  //if (((naMinimalPoly==NULL) && (naI==NULL)) || !naIsChar0)
2077  //{
2078  //  result->z = napInit(1);
2079  //  return (number)result;
2080  //}
2081  naNormalize(lb);
2082  naTest(la);
2083  naTest(lb);
2084  alg x = napCopy(a->z);
2085  number t = napLcm(b->z); // get all denom of b->z
2086  if (!nacIsOne(t))
2087  {
2088    number bt, r;
2089    alg xx=x;
2090    while (xx!=NULL)
2091    {
2092      bt = nacGcd(t, xx->ko);
2093      r = nacMult(t, xx->ko);
2094      nacDelete(&(xx->ko));
2095      xx->ko = nacDiv(r, bt);
2096      nacNormalize(xx->ko);
2097      nacDelete(&bt);
2098      nacDelete(&r);
2099      xx=xx->ne;
2100    }
2101  }
2102  nacDelete(&t);
2103  result->z = x;
2104#ifdef HAVE_FACTORY
2105  if (b->n!=NULL)
2106  {
2107    result->z=singclap_alglcm(result->z,b->n);
2108    napDelete(&x);
2109  }
2110#endif
2111  naTest(la);
2112  naTest(lb);
2113  naTest((number)result);
2114  return ((number)result);
2115}
2116
2117/*2
2118* input: a set of constant polynomials
2119* sets the global variable naI
2120*/
2121void naSetIdeal(ideal I)
2122{
2123  int i;
2124
2125  if (idIs0(I))
2126  {
2127    for (i=naI->anz-1; i>=0; i--)
2128      napDelete(&naI->liste[i]);
2129    Free((ADDRESS)naI,sizeof(*naI));
2130    naI=NULL;
2131  }
2132  else
2133  {
2134    lnumber h;
2135    number a;
2136    alg x;
2137
2138    naI=(naIdeal)Alloc(sizeof(*naI));
2139    naI->anz=IDELEMS(I);
2140    naI->liste=(alg*)Alloc(naI->anz*sizeof(alg));
2141    for (i=IDELEMS(I)-1; i>=0; i--)
2142    {
2143      h=(lnumber)pGetCoeff(I->m[i]);
2144      /* We only need the enumerator of h, as we expect it to be a polynomial */
2145      naI->liste[i]=napCopy(h->z);
2146      /* If it isn't normalized (lc = 1) do this */
2147      if (!nacIsOne(naI->liste[i]->ko))
2148      {
2149        x=naI->liste[i];
2150        a=nacCopy(x->ko);
2151        a=nacDiv(nacInit(1),a);
2152        napMultN(x,a);
2153        nacDelete(&a);
2154      }
2155    }
2156  }
2157}
2158
2159/*2
2160* map Z/p -> Q(a)
2161*/
2162number naMapP0(number c)
2163{
2164  if (npIsZero(c)) return NULL;
2165  lnumber l=(lnumber)Alloc(sizeof(rnumber));
2166  l->s=2;
2167  l->z=(alg)Alloc0(napMonomSize);
2168  int i=(int)c;
2169  if (i>(naPrimeM>>2)) i-=naPrimeM;
2170  l->z->ko=nlInit(i);
2171  l->n=NULL;
2172  return (number)l;
2173}
2174
2175/*2
2176* map Q -> Q(a)
2177*/
2178number naMap00(number c)
2179{
2180  if (nlIsZero(c)) return NULL;
2181  lnumber l=(lnumber)Alloc(sizeof(rnumber));
2182  l->s=0;
2183  l->z=(alg)Alloc0(napMonomSize);
2184  l->z->ko=nlCopy(c);
2185  l->n=NULL;
2186  return (number)l;
2187}
2188
2189/*2
2190* map Z/p -> Z/p(a)
2191*/
2192number naMapPP(number c)
2193{
2194  if (npIsZero(c)) return NULL;
2195  lnumber l=(lnumber)Alloc(sizeof(rnumber));
2196  l->s=2;
2197  l->z=(alg)Alloc0(napMonomSize);
2198  l->z->ko=c; /* omit npCopy, because npCopy is a no-op */
2199  l->n=NULL;
2200  return (number)l;
2201}
2202
2203/*2
2204* map Z/p' -> Z/p(a)
2205*/
2206number naMapPP1(number c)
2207{
2208  if (npIsZero(c)) return NULL;
2209  int i=(int)c;
2210  if (i>naPrimeM) i-=naPrimeM;
2211  number n=npInit(i);
2212  if (npIsZero(n)) return NULL;
2213  lnumber l=(lnumber)Alloc(sizeof(rnumber));
2214  l->s=2;
2215  l->z=(alg)Alloc0(napMonomSize);
2216  l->z->ko=n;
2217  l->n=NULL;
2218  return (number)l;
2219}
2220
2221/*2
2222* map Q -> Z/p(a)
2223*/
2224number naMap0P(number c)
2225{
2226  if (nlIsZero(c)) return NULL;
2227  number n=npInit(nlInt(c));
2228  if (npIsZero(n)) return NULL;
2229  lnumber l=(lnumber)Alloc(sizeof(rnumber));
2230  l->s=2;
2231  l->z=(alg)Alloc0(napMonomSize);
2232  l->z->ko=n;
2233  l->n=NULL;
2234  return (number)l;
2235}
2236
2237static number (*nacMap)(number);
2238static int naParsToCopy;
2239static alg napMap(alg p)
2240{
2241  alg w, a;
2242
2243  if (p==NULL) return NULL;
2244  a = w = (alg)Alloc0(napMonomSize);
2245  memcpy(a->e, p->e, naParsToCopy * SIZEOF_PARAMETER);
2246  w->ko = nacMap(p->ko);
2247  loop
2248  {
2249    p=p->ne;
2250    if (p==NULL) break;
2251    a->ne = (alg)Alloc0(napMonomSize);
2252    a = a->ne;
2253    memcpy(a->e, p->e, naParsToCopy * SIZEOF_PARAMETER);
2254    a->ko = nacMap(p->ko);
2255  }
2256  a->ne = NULL;
2257  return w;
2258}
2259
2260/*2
2261* map _(a) -> _(b)
2262*/
2263number naMapQaQb(number c)
2264{
2265  if (c==NULL) return NULL;
2266  lnumber erg= (lnumber)Alloc0(sizeof(rnumber));
2267  lnumber src =(lnumber)c;
2268  erg->s=src->s;
2269  erg->z=napMap(src->z);
2270  erg->n=napMap(src->n);
2271  return (number)erg;
2272}
2273
2274BOOLEAN naSetMap(int c, char ** par, int nop, number minpol)
2275{
2276  if (currRing->ch==1) /* -> Q(a) */
2277  {
2278    if (c == 0)
2279    {
2280      nMap = naMap00;   /*Q -> Q(a)*/
2281      return TRUE;
2282    }
2283    if (c>1)
2284    {
2285      if (par==NULL)
2286      {
2287        naPrimeM = c;
2288        nMap = naMapP0;  /* Z/p -> Q(a)*/
2289        return TRUE;
2290      }
2291      else
2292      {
2293        return FALSE;   /* GF(q) -> Q(a) */
2294      }
2295    }
2296    if (c<0)
2297    {
2298      return FALSE;   /* Z/p(a) -> Q(b)*/
2299    }
2300    if (c==1)
2301    {
2302      int i;
2303      naParsToCopy=0;
2304      for(i=0;i<nop;i++)
2305      {
2306        if ((i>=currRing->P)
2307        ||(strcmp(par[i],currRing->parameter[i])!=0))
2308           return FALSE;
2309        naParsToCopy++;
2310      }
2311      nacMap=nacCopy;
2312      nMap=naMapQaQb;
2313      return TRUE;   /* Q(a) -> Q(a) */
2314    }
2315  }
2316  /*-----------------------------------------------------*/
2317  if (currRing->ch<0) /* -> Z/p(a) */
2318  {
2319    if (c == 0)
2320    {
2321      nMap = naMap0P;   /*Q -> Z/p(a)*/
2322      return TRUE;
2323    }
2324    if (c>1)
2325    {
2326      if (par==NULL)
2327      {
2328        if (c==npPrimeM)
2329        {
2330          nMap = naMapPP;  /* Z/p -> Z/p(a)*/
2331          return TRUE;
2332        }
2333        else
2334        {
2335          naPrimeM = c;
2336          nMap = naMapPP1;  /* Z/p' -> Z/p(a)*/
2337          return TRUE;
2338        }
2339      }
2340      else
2341      {
2342        return FALSE;   /* GF(q) ->Z/p(a) */
2343      }
2344    }
2345    if (c<0)
2346    {
2347      if (c==currRing->ch)
2348      {
2349        nacMap=nacCopy;
2350      }
2351      else
2352      {
2353        npMapPrime=-c;
2354        nacMap = npMapP;
2355      }
2356      int i;
2357      naParsToCopy=0;
2358      for(i=0;i<nop;i++)
2359      {
2360        if ((i>=currRing->P)
2361        ||(strcmp(par[i],currRing->parameter[i])!=0))
2362           return FALSE;
2363        naParsToCopy++;
2364      }
2365      nMap=naMapQaQb;
2366      return TRUE;   /* Z/p(a),Z/p'(a) -> Z/p(b)*/
2367    }
2368    if (c==1)
2369    {
2370      return FALSE;   /* Q(a) -> Z/p(b) */
2371    }
2372  }
2373  return FALSE;      /* default */
2374}
2375
2376/*2
2377* convert a alg number into a poly
2378*/
2379poly naPermNumber(number z, int * par_perm, int P)
2380{
2381  if (z==NULL) return NULL;
2382  poly res=NULL;
2383  poly p;
2384  napoly za=((lnumber)z)->z;
2385  do
2386  {
2387    p=pInit();
2388    pNext(p)=NULL;
2389    nNew(&pGetCoeff(p));
2390    int i;
2391    for(i=pVariables;i;i--)
2392       pSetExp(p,i, 0);
2393    pSetComp(p, 0);
2394    napoly pa=NULL;
2395    if (currRing->parameter!=NULL)
2396    {
2397      pGetCoeff(p)=(number)Alloc0(sizeof(rnumber));
2398      ((lnumber)pGetCoeff(p))->s=2;
2399      ((lnumber)pGetCoeff(p))->z=napInitz(nacCopy(napGetCoeff(za)));
2400      pa=((lnumber)pGetCoeff(p))->z;
2401    }
2402    else
2403    {
2404      pGetCoeff(p)=nCopy(napGetCoeff(za));
2405    }
2406    for(i=0;i<P;i++)
2407    {
2408      if(za->e[i]!=0)
2409      {
2410        if(par_perm[i]>0)
2411          pSetExp(p,par_perm[i],za->e[i]);
2412        else if((par_perm[i]<0)&&(pa!=NULL))
2413          pa->e[-par_perm[i]-1]=za->e[i];
2414        else
2415        {
2416          pDelete(&p);
2417          break;
2418        }
2419      }
2420    }
2421    if (p!=NULL)
2422    {
2423      pSetm(p);
2424      pTest(p);
2425      res=pAdd(res,p);
2426    }
2427    za=za->ne;
2428  }
2429  while (za!=NULL);
2430  pTest(res);
2431  return res;
2432}
2433
2434#ifdef LDEBUG
2435BOOLEAN naDBTest(number a, char *f,int l)
2436{
2437  lnumber x=(lnumber)a;
2438  if (x == NULL)
2439    return TRUE;
2440#ifdef MDEBUG
2441  mmDBTestBlock(a,sizeof(rnumber),f,l);
2442#endif
2443  alg p = x->z;
2444  if (p==NULL)
2445  {
2446    Print("0/* in %s:%d\n",f,l);
2447    return FALSE;
2448  }
2449  while(p!=NULL)
2450  {
2451    if ((naIsChar0 && nlIsZero(p->ko))
2452    || ((!naIsChar0) && npIsZero(p->ko)))
2453    {
2454      Print("coeff 0 in %s:%d\n",f,l);
2455      return FALSE;
2456    }
2457    if((naMinimalPoly!=NULL)&&(p->e[0]>naMinimalPoly->e[0])
2458    &&(p!=naMinimalPoly))
2459    {
2460      Print("deg>minpoly in %s:%d\n",f,l);
2461      return FALSE;
2462    }
2463    //if (naIsChar0 && (((int)p->ko &3) == 0) && (p->ko->s==0) && (x->s==2))
2464    //{
2465    //  Print("normalized with non-normal coeffs in %s:%d\n",f,l);
2466    //  return FALSE;
2467    //}
2468    if (naIsChar0 && !(nlDBTest(p->ko,f,l)))
2469      return FALSE;
2470#ifdef MDEBUG
2471    mmDBTestBlock(p,napMonomSize,f,l);
2472#endif
2473    p = p->ne;
2474  }
2475  p = x->n;
2476  while(p!=NULL)
2477  {
2478    if (naIsChar0 && !(nlDBTest(p->ko,f,l)))
2479      return FALSE;
2480#ifdef MDEBUG
2481    if (!mmDBTestBlock(p,napMonomSize,f,l))
2482      return FALSE;
2483#endif
2484    p = p->ne;
2485  }
2486  return TRUE;
2487}
2488#endif
2489
Note: See TracBrowser for help on using the repository browser.