source: git/Singular/longalg.cc @ b45d97

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