source: git/kernel/ffields.cc @ 599326

spielwiese
Last change on this file since 599326 was 599326, checked in by Kai Krüger <krueger@…>, 14 years ago
Anne, Kai, Frank: - changes to #include "..." statements to allow cleaner build structure - affected directories: omalloc, kernel, Singular - not yet done: IntergerProgramming git-svn-id: file:///usr/local/Singular/svn/trunk@13032 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 13.4 KB
Line 
1/****************************************
2*  Computer Algebra System SINGULAR     *
3****************************************/
4/* $Id$ */
5/*
6* ABSTRACT: finite fields with a none-prime number of elements (via tables)
7*/
8
9#include <string.h>
10#include <kernel/mod2.h>
11#include <mylimits.h>
12#include <kernel/febase.h>
13#include <omalloc.h>
14#include <kernel/numbers.h>
15#include <kernel/ring.h>
16#include <kernel/ffields.h>
17
18int nfCharQ=0;  /* the number of elemts: q*/
19int nfM1;       /*representation of -1*/
20int nfCharP=0;  /* the characteristic: p*/
21static int nfCharQ1=0; /* q-1 */
22unsigned short *nfPlus1Table=NULL; /* the table i=log(z^i) -> log(z^i+1) */
23/* the q's from the table 'fftable' */
24unsigned short fftable[]={
25    4,  8, 16, 32, 64, 128, 256, 512,1024,2048,4096,8192,16384, 32768,
26/*2^2 2^3 2^4 2^5 2^6  2^7  2^8  2^9 2^10 2^11 2^12 2^13  2^14  2^15*/
27    9, 27, 81,243,729,2187, 6561,19683,59049,
28/*3^2 3^3 3^4 3^5 3^6  3^7  3^8   3^9  3^10*/
29   25,125,625,3125,15625,
30/*5^2 5^3 5^4 5^5  5^6*/
31   49,343,2401,16807,
32/*7^2 7^3  7^4 7^5*/
33   121,1331, 14641,
34/*11^2 11^3  11^4*/
35  169, 2197, 28561,
36/*13^2 13^3  13^4*/
37  289, 4913,
38/*17^2 17^3*/
39  361, 6859,
40/*19^2 19^3*/
41  529, 12167,
42/*23^2 23^3*/
43  841, 24389,
44/*29^2 29^3*/
45  961, 29791,
46/*31^2 31^3*/
47  1369, 50653,
48/*37^2  37^3*/
49  1681, /*41^2*/
50  1849, /*43^2*/
51  2209, /*47^2*/
52  2809, /*53^2*/
53  3481, /*59^2*/
54  3721, /*61^2*/
55  4489, /*67^2*/
56  5041, /*71^2*/
57  5329, /*73^2*/
58  6241, /*79^2*/
59  6889, /*83^2*/
60  7921, /*89^2*/
61  9409, /*97^2*/
62  10201, /*101^2*/
63  10609, /*103^2*/
64  11449, /*107^2*/
65  11881, /*109^2*/
66  12769, /*113^2*/
67  16129, /*127^2*/
68  17161, /*131^2*/
69  18769, /*137^2*/
70  19321, /*139^2*/
71  22201, /*149^2*/
72  22801, /*151^2*/
73  24649, /*157^2*/
74  26569, /*163^2*/
75  27889, /*167^2*/
76  29929, /*173^2*/
77  32041, /*179^2*/
78  32761, /*181^2*/
79  36481, /*191^2*/
80  37249, /*193^2*/
81  38809, /*197^2*/
82  39601, /*199^2*/
83  49729, /*223^2*/
84  44521, /*211^2*/
85  51529, /*227^2*/
86  52441, /*229^2*/
87  54289, /*233^2*/
88  57121, /*239^2*/
89  58081, /*241^2*/
90  63001, /*251^2*/
91  0 };
92
93/*1
94* numbers in GF(p^n):
95* let nfCharQ=q=nfCharP^n=p^n
96* GF(q)\{0} will be generated by powers of an element Z
97* Z^i will be represented by the int i, 1 by the int 0, 0 by the int q=nfChar
98*/
99
100#ifdef LDEBUG
101/*2
102* debugging: is a a valid representation of a number ?
103*/
104BOOLEAN nfDBTest (number a, const char *f, const int l)
105{
106  if (((long)a<0L) || ((long)a>(long)nfCharQ))
107  {
108    Print("wrong %d in %s:%d\n",(int)((long)a),f,l);
109    return FALSE;
110  }
111  int i=0;
112  do
113  {
114    if (nfPlus1Table[i]>nfCharQ)
115    {
116      Print("wrong table %d=%d in %s:%d\n",i,nfPlus1Table[i],f,l);
117      return FALSE;
118    }
119    i++;
120  } while (i<nfCharQ);
121  return TRUE;
122}
123#define nfTest(N) nfDBTest(N,__FILE__,__LINE__)
124#endif
125
126/*2
127* k >= 0 ?
128*/
129BOOLEAN nfGreaterZero (number k)
130{
131#ifdef LDEBUG
132  nfTest(k);
133#endif
134  return !nfIsZero(k) && !nfIsMOne(k);
135}
136
137/*2
138* a*b
139*/
140number nfMult (number a,number b)
141{
142#ifdef LDEBUG
143  nfTest(a);
144  nfTest(b);
145#endif
146  if (((long)a == (long)nfCharQ) || ((long)b == (long)nfCharQ))
147    return (number)(long)nfCharQ;
148  /*else*/
149  int i=(int)((long)a+(long)b);
150  if (i>=nfCharQ1) i-=nfCharQ1;
151#ifdef LDEBUG
152  nfTest((number)(long)i);
153#endif
154  return (number)(long)i;
155}
156
157/*2
158* int -> number
159*/
160number nfInit (int i, const ring r)
161{
162  // Hmm .. this is just to prevent initialization
163  // from nfInitChar to go into an infinite loop
164  if (i==0) return (number)(long)nfCharQ;
165  while (i <  0)    i += nfCharP;
166  while (i >= nfCharP) i -= nfCharP;
167  if (i==0) return (number)(long)nfCharQ;
168  unsigned short c=0;
169  while (i>1)
170  {
171    c=nfPlus1Table[c];
172    i--;
173  }
174#ifdef LDEBUG
175  nfTest((number)(long)c);
176#endif
177  return (number)(long)c;
178}
179
180/*
181* the generating element `z`
182*/
183number nfPar (int i)
184{
185  return (number)1;
186}
187
188/*2
189* the degree of the "alg. number"
190*/
191int nfParDeg(number n)
192{
193#ifdef LDEBUG
194  nfTest(n);
195#endif
196  if((long)nfCharQ == (long)n) return -1;
197  return (int)((long)n);
198}
199
200/*2
201* number -> int
202*/
203int nfInt (number &n, const ring r)
204{
205  return 0;
206}
207
208/*2
209* a + b
210*/
211number nfAdd (number a, number b)
212{
213/*4 z^a+z^b=z^b*(z^(a-b)+1), if a>=b; *
214*          =z^a*(z^(b-a)+1)  if a<b  */
215#ifdef LDEBUG
216  nfTest(a);
217  nfTest(b);
218#endif
219  if ((long)nfCharQ == (long)a) return b;
220  if ((long)nfCharQ == (long)b) return a;
221  long zb,zab,r;
222  if ((long)a >= (long)b)
223  {
224    zb = (long)b;
225    zab = (long)a-(long)b;
226  }
227  else
228  {
229    zb = (long)a;
230    zab = (long)b-(long)a;
231  }
232#ifdef LDEBUG
233  nfTest((number)zab);
234#endif
235  if (nfPlus1Table[zab]==nfCharQ) r=(long)nfCharQ; /*if z^(a-b)+1 =0*/
236  else
237  {
238    r= zb+(long)nfPlus1Table[zab];
239    if(r>=(long)nfCharQ1) r-=(long)nfCharQ1;
240  }
241#ifdef LDEBUG
242  nfTest((number)r);
243#endif
244  return (number)r;
245}
246
247/*2
248* a - b
249*/
250number nfSub (number a, number b)
251{
252  number mb = nfNeg(b);
253  return nfAdd(a,mb);
254}
255
256/*2
257* a == 0 ?
258*/
259BOOLEAN nfIsZero (number  a)
260{
261#ifdef LDEBUG
262  nfTest(a);
263#endif
264  return (long)nfCharQ == (long)a;
265}
266
267/*2
268* a == 1 ?
269*/
270BOOLEAN nfIsOne (number a)
271{
272#ifdef LDEBUG
273  nfTest(a);
274#endif
275  return 0L == (long)a;
276}
277
278/*2
279* a == -1 ?
280*/
281BOOLEAN nfIsMOne (number a)
282{
283#ifdef LDEBUG
284  nfTest(a);
285#endif
286  if (0L == (long)a) return FALSE; /* special handling of char 2*/
287  return (long)nfM1 == (long)a;
288}
289
290/*2
291* a / b
292*/
293number nfDiv (number a,number b)
294{
295#ifdef LDEBUG
296  nfTest(b);
297#endif
298  if ((long)b==(long)nfCharQ)
299  {
300    WerrorS(nDivBy0);
301    return (number)((long)nfCharQ);
302  }
303#ifdef LDEBUG
304  nfTest(a);
305#endif
306  if ((long)a==(long)nfCharQ)
307    return (number)((long)nfCharQ);
308  /*else*/
309  long s = (long)a - (long)b;
310  if (s < 0L)
311    s += (long)nfCharQ1;
312#ifdef LDEBUG
313  nfTest((number)s);
314#endif
315  return (number)s;
316}
317
318/*2
319* 1 / c
320*/
321number  nfInvers (number c)
322{
323#ifdef LDEBUG
324  nfTest(c);
325#endif
326  if ((long)c==(long)nfCharQ)
327  {
328    WerrorS(nDivBy0);
329    return (number)((long)nfCharQ);
330  }
331#ifdef LDEBUG
332  nfTest(((number)((long)nfCharQ1-(long)c)));
333#endif
334  return (number)((long)nfCharQ1-(long)c);
335}
336
337/*2
338* -c
339*/
340number nfNeg (number c)
341{
342/*4 -z^c=z^c*(-1)=z^c*nfM1*/
343#ifdef LDEBUG
344  nfTest(c);
345#endif
346  if ((long)nfCharQ == (long)c) return c;
347  long i=(long)c+(long)nfM1;
348  if (i>=(long)nfCharQ1) i-=(long)nfCharQ1;
349#ifdef LDEBUG
350  nfTest((number)i);
351#endif
352  return (number)i;
353}
354
355/*2
356* a > b ?
357*/
358BOOLEAN nfGreater (number a,number b)
359{
360#ifdef LDEBUG
361  nfTest(a);
362  nfTest(b);
363#endif
364  return (long)a != (long)b;
365}
366
367/*2
368* a == b ?
369*/
370BOOLEAN nfEqual (number a,number b)
371{
372#ifdef LDEBUG
373  nfTest(a);
374  nfTest(b);
375#endif
376  return (long)a == (long)b;
377}
378
379/*2
380* write via StringAppend
381*/
382void nfWrite (number &a, const ring r)
383{
384#ifdef LDEBUG
385  nfTest(a);
386#endif
387  if ((long)a==(long)nfCharQ)  StringAppendS("0");
388  else if ((long)a==0L)   StringAppendS("1");
389  else if (nfIsMOne(a))   StringAppendS("-1");
390  else
391  {
392    StringAppendS(r->parameter[0]);
393    if ((long)a!=1L)
394    {
395      if(r->ShortOut==0)  StringAppendS("^");
396      StringAppend("%d",(int)((long)a));
397    }
398  }
399}
400
401/*2
402*
403*/
404char * nfName(number a)
405{
406#ifdef LDEBUG
407  nfTest(a);
408#endif
409  char *s;
410  char *nfParameter=currRing->parameter[0];
411  if (((long)a==(long)nfCharQ) || ((long)a==0L)) return NULL;
412  else if ((long)a==1L)
413  {
414    return omStrDup(nfParameter);
415  }
416  else
417  {
418    s=(char *)omAlloc(4+strlen(nfParameter));
419    sprintf(s,"%s%d",nfParameter,(int)((long)a));
420  }
421  return s;
422}
423/*2
424* c ^ i with i>=0
425*/
426void nfPower (number a, int i, number * result)
427{
428#ifdef LDEBUG
429  nfTest(a);
430#endif
431  if (i==0)
432  {
433    //*result=nfInit(1);
434    *result = (number)0L;
435  }
436  else if (i==1)
437  {
438    *result = a;
439  }
440  else
441  {
442    nfPower(a,i-1,result);
443    *result = nfMult(a,*result);
444  }
445#ifdef LDEBUG
446  nfTest(*result);
447#endif
448}
449
450/*4
451* read an integer (with reduction mod p)
452*/
453static const char* nfEati(const char *s, int *i)
454{
455  if (*s >= '0' && *s <= '9')
456  {
457    *i = 0;
458    do
459    {
460      *i *= 10;
461      *i += *s++ - '0';
462      if (*i > (MAX_INT_VAL / 10)) *i = *i % nfCharP;
463    }
464    while (*s >= '0' && *s <= '9');
465    if (*i >= nfCharP) *i = *i % nfCharP;
466  }
467  else *i = 1;
468  return s;
469}
470
471/*2
472* read a number
473*/
474const char * nfRead (const char *s, number *a)
475{
476  int i;
477  number z;
478  number n;
479
480  s = nfEati(s, &i);
481  z=nfInit(i, currRing);
482  *a=z;
483  if (*s == '/')
484  {
485    s++;
486    s = nfEati(s, &i);
487    n=nfInit(i, currRing);
488    *a = nfDiv(z,n);
489  }
490  char *nfParameter=currRing->parameter[0];
491  if (strncmp(s,nfParameter,strlen(nfParameter))==0)
492  {
493    s+=strlen(nfParameter);
494    if ((*s >= '0') && (*s <= '9'))
495    {
496      s=eati(s,&i);
497      while (i>=nfCharQ1) i-=nfCharQ1;
498    }
499    else
500      i=1;
501    z=(number)(long)i;
502    *a=nfMult(*a,z);
503  }
504#ifdef LDEBUG
505  nfTest(*a);
506#endif
507  return s;
508}
509
510#ifdef HAVE_FACTORY
511int gf_tab_numdigits62 ( int q );
512int convertback62 ( char * p, int n );
513#else
514static int gf_tab_numdigits62 ( int q )
515{
516    if ( q < 62 )          return 1;
517    else  if ( q < 62*62 ) return 2;
518    /*else*/               return 3;
519}
520
521static int convback62 ( char c )
522{
523    if ( c >= '0' && c <= '9' )
524        return int(c) - int('0');
525    else  if ( c >= 'A' && c <= 'Z' )
526        return int(c) - int('A') + 10;
527    else
528        return int(c) - int('a') + 36;
529}
530
531static int convertback62 ( char * p, int n )
532{
533    int r = 0;
534    for ( int j = 0; j < n; j++ )
535        r = r * 62 + convback62( p[j] );
536    return r;
537}
538#endif
539
540int nfMinPoly[16];
541
542void nfShowMipo()
543{
544  int i=nfMinPoly[0];
545  int j=0;
546  loop
547  {
548    j++;
549    if (nfMinPoly[j]!=0)
550      StringAppend("%d*%s^%d",nfMinPoly[j],currRing->parameter[0],i);
551    i--;
552    if(i<0) break;
553    if (nfMinPoly[j]!=0)
554      StringAppendS("+");
555  }
556}
557
558static void nfReadMipo(char *s)
559{
560  const char *l=strchr(s,';')+1;
561  char *n;
562  int i=strtol(l,&n,10);
563  l=n;
564  int j=1;
565  nfMinPoly[0]=i;
566  while(i>=0)
567  {
568    nfMinPoly[j]=strtol(l,&n,10);
569    if (l==n) break;
570    l=n;
571    j++;
572    i--;
573  }
574  if (i>=0)
575  {
576    WerrorS("error in reading minpoly from gftables");
577  }
578}
579
580/*2
581* init global variables from files 'gftables/%d'
582*/
583void nfSetChar(int c, char **param)
584{
585  //Print("GF(%d)\n",c);
586  if ((c==nfCharQ)||(c==-nfCharQ))
587    /*this field is already set*/  return;
588  int i=0;
589  while ((fftable[i]!=c) && (fftable[i]!=0)) i++;
590  if (fftable[i]==0)
591    return;
592  if (nfCharQ > 1)
593  {
594    omFreeSize( (ADDRESS)nfPlus1Table,nfCharQ*sizeof(unsigned short) );
595    nfPlus1Table=NULL;
596  }
597  if ((c>1) || (c<0))
598  {
599    if (c>1) nfCharQ = c;
600    else     nfCharQ = -c;
601    char buf[100];
602    sprintf(buf,"gftables/%d",nfCharQ);
603    FILE * fp = feFopen(buf,"r",NULL,TRUE);
604    if (fp==NULL)
605    {
606      return;
607    }
608    if(!fgets( buf, sizeof(buf), fp)) return;
609    if(strcmp(buf,"@@ factory GF(q) table @@\n")!=0)
610    {
611      goto err;
612    }
613    if(!fgets( buf, sizeof(buf), fp))
614    {
615      goto err;
616    }
617    int q;
618    sscanf(buf,"%d %d",&nfCharP,&q);
619    nfReadMipo(buf);
620    nfCharQ1=nfCharQ-1;
621    //Print("nfCharQ=%d,nfCharQ1=%d,mipo=>>%s<<\n",nfCharQ,nfCharQ1,buf);
622    nfPlus1Table= (unsigned short *)omAlloc( (nfCharQ)*sizeof(unsigned short) );
623    int digs = gf_tab_numdigits62( nfCharQ );
624    char * bufptr;
625    int i = 1;
626    int k;
627    while ( i < nfCharQ )
628    {
629      fgets( buf, sizeof(buf), fp);
630      //( strlen( buffer ) == (size_t)digs * 30, "illegal table" );
631      bufptr = buf;
632      k = 0;
633      while ( (i < nfCharQ) && (k < 30) )
634      {
635        nfPlus1Table[i] = convertback62( bufptr, digs );
636        if(nfPlus1Table[i]>nfCharQ)
637        {
638          Print("wrong entry %d: %d(%c%c%c)\n",i,nfPlus1Table[i],bufptr[0],bufptr[1],bufptr[2]);
639        }
640        bufptr += digs;
641        if (nfPlus1Table[i]==nfCharQ)
642        {
643          if(i==nfCharQ1)
644          {
645            nfM1=0;
646          }
647          else
648          {
649            nfM1=i;
650          }
651        }
652        i++; k++;
653      }
654    }
655    nfPlus1Table[0]=nfPlus1Table[nfCharQ1];
656  }
657  else
658    nfCharQ=0;
659#ifdef LDEBUG
660  nfTest((number)0);
661#endif
662  return;
663err:
664  Werror("illegal GF-table %d",nfCharQ);
665}
666
667/*2
668* map Z/p -> GF(p,n)
669*/
670number nfMapP(number c)
671{
672  return nfInit((int)((long)c), currRing);
673}
674
675/*2
676* map GF(p,n1) -> GF(p,n2), n1 < n2, n1 | n2
677*/
678int nfMapGG_factor;
679number nfMapGG(number c)
680{
681  int i=(long)c;
682  i*= nfMapGG_factor;
683  while (i >nfCharQ1) i-=nfCharQ1;
684  return (number)((long)i);
685}
686/*2
687* map GF(p,n1) -> GF(p,n2), n1 > n2, n2 | n1
688*/
689number nfMapGGrev(number c)
690{
691  int ex=(int)((long)c);
692  if ((ex % nfMapGG_factor)==0)
693    return (number)(((long)ex) / ((long)nfMapGG_factor));
694  else
695    return (number)(long)nfCharQ; /* 0 */
696}
697
698/*2
699* set map function nMap ... -> GF(p,n)
700*/
701nMapFunc nfSetMap(const ring src, const ring dst)
702{
703  if (rField_is_GF(src,nfCharQ))
704  {
705    return ndCopy;   /* GF(p,n) -> GF(p,n) */
706  }
707  if (rField_is_GF(src))
708  {
709    int q=src->ch;
710    if ((nfCharQ % q)==0) /* GF(p,n1) -> GF(p,n2), n2 > n1 */
711    {
712      // check if n2 is a multiple of n1
713      int n1=1;
714      int qq=nfCharP;
715      while(qq!=q) { qq *= nfCharP; n1++; }
716      int n2=1;
717      qq=nfCharP;
718      while(qq!=nfCharQ) { qq *= nfCharP; n2++; }
719      Print("map %d^%d -> %d^%d\n",nfCharP,n1,nfCharP,n2);
720      if ((n2 % n1)==0)
721      {
722        int save_ch=currRing->ch;
723        char **save_par=currRing->parameter;
724        nfSetChar(src->ch,src->parameter);
725        int nn=nfPlus1Table[0];
726        nfSetChar(save_ch,save_par);
727        nfMapGG_factor= nfPlus1Table[0] / nn;
728        Print("nfMapGG_factor=%d (%d / %d)\n",nfMapGG_factor, nfPlus1Table[0], nn);
729        return nfMapGG;
730      }
731      else if ((n1 % n2)==0)
732      {
733        nfMapGG_factor= (n1/n2);
734        return nfMapGGrev;
735      }
736      else
737        return NULL;
738    }
739  }
740  if (rField_is_Zp(src,nfCharP))
741  {
742    return nfMapP;    /* Z/p -> GF(p,n) */
743  }
744  return NULL;     /* default */
745}
Note: See TracBrowser for help on using the repository browser.