source: git/Singular/ffields.cc @ 50cbdc

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