source: git/kernel/longalg.cc @ 64345a4

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