source: git/kernel/ffields.cc @ 68349d

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