source: git/Singular/ffields.cc @ 400884

fieker-DuValspielwiese
Last change on this file since 400884 was 667247, checked in by Hans Schönemann <hannes@…>, 27 years ago
* hannes: -fixed exitVoice in febase.cc -changed used of TEST in ideals.cc ipassign.cc ipconv.cc mmallocb.c modulop.cc polys2.cc numbers.cc - made nfCharQ, nfCharM1 extern in ffields.cc git-svn-id: file:///usr/local/Singular/svn/trunk@226 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 11.4 KB
RevLine 
[0e1846]1/****************************************
2*  Computer Algebra System SINGULAR     *
3****************************************/
[667247]4/* $Id: ffields.cc,v 1.11 1997-05-02 15:10:12 Singular Exp $ */
[0e1846]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"
[50b2df]12#include "tok.h"
[0e1846]13#include "febase.h"
14#include "mmemory.h"
15#include "numbers.h"
16#include "ffields.h"
17
[667247]18int nfCharQ=0;  /* the number of elemts: q*/
19int nfM1;       /*representation of -1*/
[0e1846]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*/
[077e9c]28    9, 27, 81,243,729,2187, 6561,19683,
[0e1846]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*/
[077e9c]34   121,1331, 14641,
[0e1846]35/*11^2 11^3  11^4*/
[077e9c]36  169, 2197, 28561,
[0e1846]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
[077e9c]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           
[0e1846]145/*2
146* k >= 0 ?
147*/
148BOOLEAN nfGreaterZero (number k)
149{
[077e9c]150#ifdef LDEBUG
151  nfTest(k);
152#endif
[0e1846]153  return !nfIsZero(k);
154}
155
156/*2
157* a*b
158*/
159number nfMult (number a,number b)
160{
[077e9c]161#ifdef LDEBUG
162  nfTest(a);
163  nfTest(b);
164#endif
[0e1846]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;
[077e9c]170#ifdef LDEBUG
171  nfTest((number)i);
172#endif
[0e1846]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  }
[077e9c]190#ifdef LDEBUG
191  nfTest((number)c);
192#endif
[0e1846]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{
[077e9c]209#ifdef LDEBUG
210  nfTest(n);
211#endif
[0e1846]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*/
[077e9c]227number nfCopy (number  k)
[0e1846]228{
[077e9c]229#ifdef LDEBUG
230  nfTest(k);
231#endif
232  return k;
[0e1846]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  */
[077e9c]242#ifdef LDEBUG
243  nfTest(a);
244  nfTest(b);
245#endif
[0e1846]246  int zb,zab,r;
247  if ((int)a >= (int)b)
248  {
249    zb = (int)b;
250    zab = (int)a-(int)b;
251  }
252  else
253  {
254    zb = (int)a;
255    zab = (int)b-(int)a;
256  }
[077e9c]257#ifdef LDEBUG
258  nfTest((number)zab);
259#endif
[0e1846]260  if (nfPlus1Table[zab]==nfCharQ) r=nfCharQ; /*if z^(a-b)+1 =0*/
261  else
262  {
263    r= zb+nfPlus1Table[zab];
264    if(r>=nfCharQ1) r-=nfCharQ1;
265  }
[077e9c]266#ifdef LDEBUG
267  nfTest((number)r);
268#endif
[0e1846]269  return (number)r;
270}
271
272/*2
273* a - b
274*/
275number nfSub (number a, number b)
276{
277  number mb = nfNeg(b);
278  return nfAdd(a,mb);
279}
280
281/*2
282* a == 0 ?
283*/
284BOOLEAN nfIsZero (number  a)
285{
[077e9c]286#ifdef LDEBUG
287  nfTest(a);
288#endif
[0e1846]289  return nfCharQ == (int)a;
290}
291
292/*2
293* a == 1 ?
294*/
295BOOLEAN nfIsOne (number a)
296{
[077e9c]297#ifdef LDEBUG
298  nfTest(a);
299#endif
[0e1846]300  return 0 == (int)a;
301}
302
303/*2
304* a == -1 ?
305*/
306BOOLEAN nfIsMOne (number a)
307{
[077e9c]308#ifdef LDEBUG
309  nfTest(a);
310#endif
[0e1846]311  return nfM1 == (int)a;
312}
313
314/*2
315* a / b
316*/
317number nfDiv (number a,number b)
318{
[077e9c]319#ifdef LDEBUG
320  nfTest(b);
321#endif
[0e1846]322  if ((int)b==nfCharQ)
323  {
324    WerrorS("div. by 0");
325    return (number)nfCharQ;
326  }
[077e9c]327#ifdef LDEBUG
328  nfTest(a);
329#endif
[0e1846]330  if ((int)a==nfCharQ)
331    return (number)nfCharQ;
332  /*else*/
333  int s = (int)a - (int)b;
334  if (s < 0)
335    s += nfCharQ1;
[077e9c]336#ifdef LDEBUG
337  nfTest((number)s);
338#endif
[0e1846]339  return (number)s;
340}
341
342/*2
343* 1 / c
344*/
345number  nfInvers (number c)
346{
[077e9c]347#ifdef LDEBUG
348  nfTest(c);
349#endif
[0e1846]350  if ((int)c==nfCharQ)
351  {
352    WerrorS("div. 1/0");
353    return (number)nfCharQ;
354  }
[077e9c]355#ifdef LDEBUG
356  nfTest(((number)(nfCharQ1-(int)c)));
357#endif
[0e1846]358  return (number)(nfCharQ1-(int)c);
359}
360
361/*2
362* -c
363*/
364number nfNeg (number c)
365{
366/*4 -z^c=z^c*(-1)=z^c*nfM1*/
[077e9c]367#ifdef LDEBUG
368  nfTest(c);
369#endif
[0e1846]370  int i=(int)c+nfM1;
371  if (i>=nfCharQ1) i-=nfCharQ1;
[077e9c]372#ifdef LDEBUG
373  nfTest((number)i);
374#endif
[0e1846]375  return (number)i;
376}
377
378/*2
379* a > b ?
380*/
381BOOLEAN nfGreater (number a,number b)
382{
[077e9c]383#ifdef LDEBUG
384  nfTest(a);
385  nfTest(b);
386#endif
[0e1846]387  return (int)a != (int)b;
388}
389
390/*2
391* a == b ?
392*/
393BOOLEAN nfEqual (number a,number b)
394{
[077e9c]395#ifdef LDEBUG
396  nfTest(a);
397  nfTest(b);
398#endif
[0e1846]399  return (int)a == (int)b;
400}
401
402/*2
403* write via StringAppend
404*/
405void nfWrite (number &a)
406{
[077e9c]407#ifdef LDEBUG
408  nfTest(a);
409#endif
[0e1846]410  if ((int)a==nfCharQ)  StringAppendS("0");
411  else if ((int)a==0)   StringAppendS("1");
[da97958]412  else                 
413  {
414    StringAppendS(nfParameter);
415    if ((int)a!=1)
416    {
417      if(pShortOut==0)  StringAppendS("^");
418      StringAppend("%d",(int)a);
419    }
420  }
[0e1846]421}
422
423/*2
424*
425*/
426char * nfName(number a)
427{
[077e9c]428#ifdef LDEBUG
429  nfTest(a);
430#endif
[0e1846]431  char *s;
432  if (((int)a==nfCharQ) || ((int)a==0)) return NULL;
433  else if ((int)a==1)
434  {
435    return mstrdup(nfParameter);
436  }
437  else
438  {
439    s=(char *)AllocL(4+strlen(nfParameter));
440    sprintf(s,"%s%d",nfParameter,(int)a);
441  }
442  return s;
443}
444/*2
445* c ^ i with i>=0
446*/
447void nfPower (number a, int i, number * result)
448{
[077e9c]449#ifdef LDEBUG
450  nfTest(a);
451#endif
[0e1846]452  if (i==0)
453  {
454    //*result=nfInit(1);
[077e9c]455    *result = (number)0;
[0e1846]456  }
457  else if (i==1)
458  {
459    //*result = nfCopy(a);
460    *result = a;
461  }
462  else
463  {
464    nfPower(a,i-1,result);
465    *result = nfMult(a,*result);
466  }
[077e9c]467#ifdef LDEBUG
468  nfTest(*result);
469#endif
[0e1846]470}
471
472/*4
473* read an integer (with reduction mod p)
474*/
475static char* nfEati(char *s, int *i)
476{
477  if (*s >= '0' && *s <= '9')
478  {
479    *i = 0;
480    do
481    {
482      *i *= 10;
483      *i += *s++ - '0';
484      if (*i > (INT_MAX / 10)) *i = *i % nfCharP;
485    }
486    while (*s >= '0' && *s <= '9');
487    if (*i >= nfCharP) *i = *i % nfCharP;
488  }
489  else *i = 1;
490  return s;
491}
492
493/*2
494* read a number
495*/
496char * nfRead (char *s, number *a)
497{
498  int i;
499  number z;
500  number n;
501
502  s = nfEati(s, &i);
503  z=nfInit(i);
504  *a=z;
505  if (*s == '/')
506  {
507    s++;
508    s = nfEati(s, &i);
509    n=nfInit(i);
510    *a = nfDiv(z,n);
511  }
512  if (strncmp(s,nfParameter,strlen(nfParameter))==0)
513  {
514    s+=strlen(nfParameter);
515    if ((*s >= '0') && (*s <= '9'))
516    {
517      s=eati(s,&i);
518      while (i>=nfCharQ1) i-=nfCharQ1;
519    }
520    else
521      i=1;
522    z=(number)i;
523    *a=nfMult(*a,z);
524  }
[077e9c]525#ifdef LDEBUG
526  nfTest(*a);
527#endif
[0e1846]528  return s;
529}
530
[40edb03]531#ifdef HAVE_FACTORY
[0e1846]532int gf_tab_numdigits62 ( int q );
533int convertback62 ( char * p, int n );
534#else
535static int gf_tab_numdigits62 ( int q )
536{
537    if ( q < 62 )          return 1;
538    else  if ( q < 62*62 ) return 2;
539    /*else*/               return 3;
540}
541
542static int convback62 ( char c )
543{
544    if ( c >= '0' && c <= '9' )
545        return int(c) - int('0');
546    else  if ( c >= 'A' && c <= 'Z' )
547        return int(c) - int('A') + 10;
548    else
549        return int(c) - int('a') + 36;
550}
551
[7fa4ba]552static int convertback62 ( char * p, int n )
[0e1846]553{
554    int r = 0;
555    for ( int j = 0; j < n; j++ )
556        r = r * 62 + convback62( p[j] );
557    return r;
558}
559#endif
560
[077e9c]561int nfMinPoly[16];
[50b2df]562
563void nfShowMipo()
564{
565  int i=nfMinPoly[0];
566  int j=0;
567  loop
568  {
569    j++;
570    if (nfMinPoly[j]!=0)
[077e9c]571      StringAppend("%d*%s^%d",nfMinPoly[j],nfParameter,i);
[50b2df]572    i--;
573    if(i<0) break;
574    if (nfMinPoly[j]!=0)
[077e9c]575      StringAppendS("+");
576  }
[50b2df]577}
578
579static void nfReadMipo(char *s)
580{
581  char *l=strchr(s,';')+1;
582  char *n;
[40edb03]583#ifdef HAVE_STRTOL 
[50b2df]584  int i=strtol(l,&n,10);
[40edb03]585#else
586  int i;
587  sscanf(l, "%d", &i);
588#endif 
[50b2df]589  l=n;
590  int j=1;
591  nfMinPoly[0]=i;
592  while(i>=0)
593  {
[40edb03]594#ifdef HAVE_STRTOL
[50b2df]595    nfMinPoly[j]=strtol(l,&n,10);
[40edb03]596#else
597    sscanf(l, "%d", &(nfMinPoly[j]));
598#endif   
[50b2df]599    if (l==n) break;
600    l=n;
601    j++;
602    i--;
603  } 
604  if (i>=0)
605  {
606    WerrorS("error in reading minpoly from gftables");
607  } 
608} 
609
[0e1846]610/*2
611* init global variables from files 'gftables/%d'
612*/
613void nfSetChar(int c, char **param)
614{
615  nfParameter=param[0];
616  if ((c==nfCharQ)||(c==-nfCharQ))
617    /*this field is already set*/  return;
618  int i=0;
619  while ((fftable[i]!=c) && (fftable[i]!=0)) i++;
620  if (fftable[i]==0)
621    return;
622  if (nfCharQ > 1)
623  {
624    Free( (ADDRESS)nfPlus1Table,nfCharQ*sizeof(CARDINAL) );
625    nfPlus1Table=NULL;
626  }
627  if ((c>1) || (c<0))
628  {
629    if (c>1) nfCharQ = c;
630    else     nfCharQ = -c;
[077e9c]631    char buf[100];
[0e1846]632    sprintf(buf,"gftables/%d",nfCharQ);
[c78b18b]633    FILE * fp = feFopen(buf,"r",NULL,FALSE);
[0e1846]634    if (fp==NULL)
635    {
[cc0296]636      sprintf(buf,"../gftables/%d",nfCharQ);
637      fp = feFopen(buf,"r",NULL,TRUE);
638      if (fp == NULL)
639      {
640        Werror("cannot find gftables/%d", nfCharQ);
641        return;
642      }
[0e1846]643    }
644    if(!fgets( buf, sizeof(buf), fp)) return;
645    if(strcmp(buf,"@@ factory GF(q) table @@\n")!=0)
646    {
647      goto err;
648    }
649    if(!fgets( buf, sizeof(buf), fp))
650    {
651      goto err;
652    }
653    int q;
654    sscanf(buf,"%d %d",&nfCharP,&q);
[50b2df]655    nfReadMipo(buf);
[0e1846]656    nfCharQ1=nfCharQ-1;
657    nfPlus1Table= (CARDINAL *)Alloc( (nfCharQ)*sizeof(CARDINAL) );
658    int digs = gf_tab_numdigits62( nfCharQ );
659    char * bufptr;
660    int i = 1;
661    int k;
662    while ( i < nfCharQ )
663    {
664      fgets( buf, sizeof(buf), fp);
665      //( strlen( buffer ) == (size_t)digs * 30, "illegal table" );
666      bufptr = buf;
667      k = 0;
668      while ( (i < nfCharQ) && (k < 30) )
669      {
670        nfPlus1Table[i] = convertback62( bufptr, digs );
[077e9c]671        if(nfPlus1Table[i]>nfCharQ)
672        {
673          Print("wrong entry %d: %d(%c%c%c)\n",i,nfPlus1Table[i],bufptr[0],bufptr[1],bufptr[2]);
674        } 
[0e1846]675        bufptr += digs;
[077e9c]676        if (nfPlus1Table[i]==nfCharQ)
677        {
678          if(i==nfCharQ1)
679          {
680            nfM1=0;
681          }
682          else
683          {
684            nfM1=i;
685          }
686        }
[0e1846]687        i++; k++;
688      }
689    }
[077e9c]690    nfPlus1Table[0]=nfPlus1Table[nfCharQ1];
[0e1846]691  }
692  else
693    nfCharQ=0;
[077e9c]694#ifdef LDEBUG
695  nfTest((number)0); 
696#endif
[0e1846]697  return;
698err:
699  Werror("illegal GF-table %d",nfCharQ);
700}
701
702/*2
703* map Z/p -> GF(p,n)
704*/
705number nfMapP(number c)
706{
707  return nfInit((int)c);
708}
709
710/*2
711* set map function nMap ... -> GF(p,n)
712*/
713BOOLEAN nfSetMap(int c, char ** par, int nop, number minpol)
714{
715  if (c==nfCharQ)
716  {
717    nMap=nfCopy;   /* GF(p,n) -> GF(p,n) */
718    return TRUE;
719  }
720  if (c==nfCharP)
721  {
722    nMap=nfMapP;    /* Z/p -> GF(p,n) */
723    return TRUE;
724  }
725  return FALSE;     /* default */
726}
727
728/*2
729* dummy modulus: return 0
730*/
731number nfIntMod(number a, number b)
732{
733  return (number)nfCharQ;
734}
Note: See TracBrowser for help on using the repository browser.