source: git/kernel/longalg.cc @ a7b15e0

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