source: git/Singular/ffields.cc @ 45ce793

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