source: git/coeffs/ffields.cc @ 3510a6

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