source: git/coeffs/ffields.cc @ 619c8f

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