source: git/Singular/ffields.cc @ c5f4b9

spielwiese
Last change on this file since c5f4b9 was c5f4b9, checked in by Olaf Bachmann <obachman@…>, 24 years ago
* get rid off pShortOut, pVectorOut * towards working with tailRings in std git-svn-id: file:///usr/local/Singular/svn/trunk@4651 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 11.3 KB
Line 
1/****************************************
2*  Computer Algebra System SINGULAR     *
3****************************************/
4/* $Id: ffields.cc,v 1.27 2000-10-19 15:00:11 obachman Exp $ */
5/*
6* ABSTRACT: finite fields with a none-prime number of elements (via tables)
7*/
8
9#include <limits.h>
10#include <string.h>
11#include "mod2.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  while (i <  0)    i += nfCharP;
183  while (i >= nfCharP) i -= nfCharP;
184  if (i==0) return (number)nfCharQ;
185  int c=0;
186  while (i>1)
187  {
188    c=nfPlus1Table[c];
189    i--;
190  }
191#ifdef LDEBUG
192  nfTest((number)c);
193#endif
194  return (number)c;
195}
196
197/*
198* the generating element `z`
199*/
200number nfPar (int i)
201{
202  return (number)1;
203}
204
205/*2
206* the degree of the "alg. number"
207*/
208int nfParDeg(number n)
209{
210#ifdef LDEBUG
211  nfTest(n);
212#endif
213  if(nfCharQ == (int)n) return -1;
214  return (int)n;
215}
216
217/*2
218* number -> int
219*/
220int nfInt (number &n)
221{
222  return 0;
223}
224
225/*2
226* a + b
227*/
228number nfAdd (number a, number b)
229{
230/*4 z^a+z^b=z^b*(z^(a-b)+1), if a>=b; *
231*          =z^a*(z^(b-a)+1)  if a<b  */
232#ifdef LDEBUG
233  nfTest(a);
234  nfTest(b);
235#endif
236  if (nfCharQ == (int)a) return b;
237  if (nfCharQ == (int)b) return a;
238  int zb,zab,r;
239  if ((int)a >= (int)b)
240  {
241    zb = (int)b;
242    zab = (int)a-(int)b;
243  }
244  else
245  {
246    zb = (int)a;
247    zab = (int)b-(int)a;
248  }
249#ifdef LDEBUG
250  nfTest((number)zab);
251#endif
252  if (nfPlus1Table[zab]==nfCharQ) r=nfCharQ; /*if z^(a-b)+1 =0*/
253  else
254  {
255    r= zb+nfPlus1Table[zab];
256    if(r>=nfCharQ1) r-=nfCharQ1;
257  }
258#ifdef LDEBUG
259  nfTest((number)r);
260#endif
261  return (number)r;
262}
263
264/*2
265* a - b
266*/
267number nfSub (number a, number b)
268{
269  number mb = nfNeg(b);
270  return nfAdd(a,mb);
271}
272
273/*2
274* a == 0 ?
275*/
276BOOLEAN nfIsZero (number  a)
277{
278#ifdef LDEBUG
279  nfTest(a);
280#endif
281  return nfCharQ == (int)a;
282}
283
284/*2
285* a == 1 ?
286*/
287BOOLEAN nfIsOne (number a)
288{
289#ifdef LDEBUG
290  nfTest(a);
291#endif
292  return 0 == (int)a;
293}
294
295/*2
296* a == -1 ?
297*/
298BOOLEAN nfIsMOne (number a)
299{
300#ifdef LDEBUG
301  nfTest(a);
302#endif
303  if (0 == (int)a) return FALSE; /* special handling of char 2*/
304  return nfM1 == (int)a;
305}
306
307/*2
308* a / b
309*/
310number nfDiv (number a,number b)
311{
312#ifdef LDEBUG
313  nfTest(b);
314#endif
315  if ((int)b==nfCharQ)
316  {
317    WerrorS("div. by 0");
318    return (number)nfCharQ;
319  }
320#ifdef LDEBUG
321  nfTest(a);
322#endif
323  if ((int)a==nfCharQ)
324    return (number)nfCharQ;
325  /*else*/
326  int s = (int)a - (int)b;
327  if (s < 0)
328    s += nfCharQ1;
329#ifdef LDEBUG
330  nfTest((number)s);
331#endif
332  return (number)s;
333}
334
335/*2
336* 1 / c
337*/
338number  nfInvers (number c)
339{
340#ifdef LDEBUG
341  nfTest(c);
342#endif
343  if ((int)c==nfCharQ)
344  {
345    WerrorS("div. 1/0");
346    return (number)nfCharQ;
347  }
348#ifdef LDEBUG
349  nfTest(((number)(nfCharQ1-(int)c)));
350#endif
351  return (number)(nfCharQ1-(int)c);
352}
353
354/*2
355* -c
356*/
357number nfNeg (number c)
358{
359/*4 -z^c=z^c*(-1)=z^c*nfM1*/
360#ifdef LDEBUG
361  nfTest(c);
362#endif
363  if (nfCharQ == (int)c) return c;
364  int i=(int)c+nfM1;
365  if (i>=nfCharQ1) i-=nfCharQ1;
366#ifdef LDEBUG
367  nfTest((number)i);
368#endif
369  return (number)i;
370}
371
372/*2
373* a > b ?
374*/
375BOOLEAN nfGreater (number a,number b)
376{
377#ifdef LDEBUG
378  nfTest(a);
379  nfTest(b);
380#endif
381  return (int)a != (int)b;
382}
383
384/*2
385* a == b ?
386*/
387BOOLEAN nfEqual (number a,number b)
388{
389#ifdef LDEBUG
390  nfTest(a);
391  nfTest(b);
392#endif
393  return (int)a == (int)b;
394}
395
396/*2
397* write via StringAppend
398*/
399void nfWrite (number &a)
400{
401#ifdef LDEBUG
402  nfTest(a);
403#endif
404  if ((int)a==nfCharQ)  StringAppendS("0");
405  else if ((int)a==0)   StringAppendS("1");
406  else if (nfIsMOne(a))   StringAppendS("-1");
407  else
408  {
409    StringAppendS(nfParameter);
410    if ((int)a!=1)
411    {
412      if(currRing->ShortOut==0)  StringAppendS("^");
413      StringAppend("%d",(int)a);
414    }
415  }
416}
417
418/*2
419*
420*/
421char * nfName(number a)
422{
423#ifdef LDEBUG
424  nfTest(a);
425#endif
426  char *s;
427  if (((int)a==nfCharQ) || ((int)a==0)) return NULL;
428  else if ((int)a==1)
429  {
430    return omStrDup(nfParameter);
431  }
432  else
433  {
434    s=(char *)omAlloc(4+strlen(nfParameter));
435    sprintf(s,"%s%d",nfParameter,(int)a);
436  }
437  return s;
438}
439/*2
440* c ^ i with i>=0
441*/
442void nfPower (number a, int i, number * result)
443{
444#ifdef LDEBUG
445  nfTest(a);
446#endif
447  if (i==0)
448  {
449    //*result=nfInit(1);
450    *result = (number)0;
451  }
452  else if (i==1)
453  {
454    *result = a;
455  }
456  else
457  {
458    nfPower(a,i-1,result);
459    *result = nfMult(a,*result);
460  }
461#ifdef LDEBUG
462  nfTest(*result);
463#endif
464}
465
466/*4
467* read an integer (with reduction mod p)
468*/
469static char* nfEati(char *s, int *i)
470{
471  if (*s >= '0' && *s <= '9')
472  {
473    *i = 0;
474    do
475    {
476      *i *= 10;
477      *i += *s++ - '0';
478      if (*i > (MAX_INT_VAL / 10)) *i = *i % nfCharP;
479    }
480    while (*s >= '0' && *s <= '9');
481    if (*i >= nfCharP) *i = *i % nfCharP;
482  }
483  else *i = 1;
484  return s;
485}
486
487/*2
488* read a number
489*/
490char * nfRead (char *s, number *a)
491{
492  int i;
493  number z;
494  number n;
495
496  s = nfEati(s, &i);
497  z=nfInit(i);
498  *a=z;
499  if (*s == '/')
500  {
501    s++;
502    s = nfEati(s, &i);
503    n=nfInit(i);
504    *a = nfDiv(z,n);
505  }
506  if (strncmp(s,nfParameter,strlen(nfParameter))==0)
507  {
508    s+=strlen(nfParameter);
509    if ((*s >= '0') && (*s <= '9'))
510    {
511      s=eati(s,&i);
512      while (i>=nfCharQ1) i-=nfCharQ1;
513    }
514    else
515      i=1;
516    z=(number)i;
517    *a=nfMult(*a,z);
518  }
519#ifdef LDEBUG
520  nfTest(*a);
521#endif
522  return s;
523}
524
525#ifdef HAVE_FACTORY
526int gf_tab_numdigits62 ( int q );
527int convertback62 ( char * p, int n );
528#else
529static int gf_tab_numdigits62 ( int q )
530{
531    if ( q < 62 )          return 1;
532    else  if ( q < 62*62 ) return 2;
533    /*else*/               return 3;
534}
535
536static int convback62 ( char c )
537{
538    if ( c >= '0' && c <= '9' )
539        return int(c) - int('0');
540    else  if ( c >= 'A' && c <= 'Z' )
541        return int(c) - int('A') + 10;
542    else
543        return int(c) - int('a') + 36;
544}
545
546static int convertback62 ( char * p, int n )
547{
548    int r = 0;
549    for ( int j = 0; j < n; j++ )
550        r = r * 62 + convback62( p[j] );
551    return r;
552}
553#endif
554
555int nfMinPoly[16];
556
557void nfShowMipo()
558{
559  int i=nfMinPoly[0];
560  int j=0;
561  loop
562  {
563    j++;
564    if (nfMinPoly[j]!=0)
565      StringAppend("%d*%s^%d",nfMinPoly[j],nfParameter,i);
566    i--;
567    if(i<0) break;
568    if (nfMinPoly[j]!=0)
569      StringAppendS("+");
570  }
571}
572
573static void nfReadMipo(char *s)
574{
575  const char *l=strchr(s,';')+1;
576  char *n;
577  int i=strtol(l,&n,10);
578  l=n;
579  int j=1;
580  nfMinPoly[0]=i;
581  while(i>=0)
582  {
583    nfMinPoly[j]=strtol(l,&n,10);
584    if (l==n) break;
585    l=n;
586    j++;
587    i--;
588  }
589  if (i>=0)
590  {
591    WerrorS("error in reading minpoly from gftables");
592  }
593}
594
595/*2
596* init global variables from files 'gftables/%d'
597*/
598void nfSetChar(int c, char **param)
599{
600  //Print("GF(%d)\n",c);
601  nfParameter=param[0];
602  if ((c==nfCharQ)||(c==-nfCharQ))
603    /*this field is already set*/  return;
604  int i=0;
605  while ((fftable[i]!=c) && (fftable[i]!=0)) i++;
606  if (fftable[i]==0)
607    return;
608  if (nfCharQ > 1)
609  {
610    omFreeSize( (ADDRESS)nfPlus1Table,nfCharQ*sizeof(CARDINAL) );
611    nfPlus1Table=NULL;
612  }
613  if ((c>1) || (c<0))
614  {
615    if (c>1) nfCharQ = c;
616    else     nfCharQ = -c;
617    char buf[100];
618#ifdef macintosh
619    sprintf(buf,"gftables:%d",nfCharQ);
620#else
621    sprintf(buf,"gftables/%d",nfCharQ);
622#endif
623    FILE * fp = feFopen(buf,"r",NULL,TRUE);
624    if (fp==NULL)
625    {
626      return;
627    }
628    if(!fgets( buf, sizeof(buf), fp)) return;
629    if(strcmp(buf,"@@ factory GF(q) table @@\n")!=0)
630    {
631      goto err;
632    }
633    if(!fgets( buf, sizeof(buf), fp))
634    {
635      goto err;
636    }
637    int q;
638    sscanf(buf,"%d %d",&nfCharP,&q);
639    nfReadMipo(buf);
640    nfCharQ1=nfCharQ-1;
641    //Print("nfCharQ=%d,nfCharQ1=%d,mipo=>>%s<<\n",nfCharQ,nfCharQ1,buf);
642    nfPlus1Table= (CARDINAL *)omAlloc( (nfCharQ)*sizeof(CARDINAL) );
643    int digs = gf_tab_numdigits62( nfCharQ );
644    char * bufptr;
645    int i = 1;
646    int k;
647    while ( i < nfCharQ )
648    {
649      fgets( buf, sizeof(buf), fp);
650      //( strlen( buffer ) == (size_t)digs * 30, "illegal table" );
651      bufptr = buf;
652      k = 0;
653      while ( (i < nfCharQ) && (k < 30) )
654      {
655        nfPlus1Table[i] = convertback62( bufptr, digs );
656        if(nfPlus1Table[i]>nfCharQ)
657        {
658          Print("wrong entry %d: %d(%c%c%c)\n",i,nfPlus1Table[i],bufptr[0],bufptr[1],bufptr[2]);
659        }
660        bufptr += digs;
661        if (nfPlus1Table[i]==nfCharQ)
662        {
663          if(i==nfCharQ1)
664          {
665            nfM1=0;
666          }
667          else
668          {
669            nfM1=i;
670          }
671        }
672        i++; k++;
673      }
674    }
675    nfPlus1Table[0]=nfPlus1Table[nfCharQ1];
676  }
677  else
678    nfCharQ=0;
679#ifdef LDEBUG
680  nfTest((number)0);
681#endif
682  return;
683err:
684  Werror("illegal GF-table %d",nfCharQ);
685}
686
687/*2
688* map Z/p -> GF(p,n)
689*/
690number nfMapP(number c)
691{
692  return nfInit((int)c);
693}
694
695/*2
696* set map function nMap ... -> GF(p,n)
697*/
698BOOLEAN nfSetMap(ring r)
699{
700  if (rField_is_GF(r,nfCharQ))
701  {
702    nMap=ndCopy;   /* GF(p,n) -> GF(p,n) */
703    return TRUE;
704  }
705  if (rField_is_Zp(r,nfCharP))
706  {
707    nMap=nfMapP;    /* Z/p -> GF(p,n) */
708    return TRUE;
709  }
710  return FALSE;     /* default */
711}
Note: See TracBrowser for help on using the repository browser.