source: git/factory/gengftables.cc @ ba5e9e

spielwiese
Last change on this file since ba5e9e was 16f511, checked in by Oleksandr Motsak <motsak@…>, 11 years ago
Fixed the usage of "config.h" (if defined HAVE_CONFIG_H)
  • Property mode set to 100644
File size: 6.7 KB
Line 
1/* emacs edit mode for this file is -*- C++ -*- */
2
3//{{{ docu
4//
5// gengftables.cc - generate addition tables used by Factory
6//   to calculate in GF(q).
7//
8// Note: This may take quite a while ...
9//
10//}}}
11
12#ifdef HAVE_CONFIG_H
13#include "config.h"
14#endif /* HAVE_CONFIG_H */
15
16#ifdef HAVE_IOSTREAM
17#include <iostream>
18#include <fstream>
19#include <strstream>
20using namespace std;
21#elif defined(HAVE_IOSTREAM_H)
22#include <iostream.h>
23#include <fstream.h>
24#include <strstream.h>
25#endif
26
27#include "cf_assert.h"
28#include "gf_tabutil.h"
29#include "cf_algorithm.h"
30#include "cf_iter.h"
31
32//{{{ constants
33//{{{ docu
34//
35// - constants.
36//
37// maxtable: maximal size of a gf_table
38// primes, primes_len:
39//   used to step through possible extensions
40//
41//}}}
42const int maxtable = 32767;
43
44const int primes_len = 42;
45static unsigned short primes [] =
46{
47      2,   3,   5,   7,  11,  13,  17,  19,
48     23,  29,  31,  37,  41,  43,  47,  53,
49     59,  61,  67,  71,  73,  79,  83,  89,
50     97, 101, 103, 107, 109, 113, 127, 131,
51    137, 139, 149, 151, 157, 163, 167, 173,
52    179, 181
53};
54//}}}
55
56//{{{ bool isIrreducible ( const CanonicalForm & f )
57//{{{ docu
58//
59// isIrreducible() - return true iff f is irreducible.
60//
61//}}}
62bool
63isIrreducible ( const CanonicalForm & f )
64{
65    CFFList F = factorize( f );
66    return F.length() == 1 && F.getFirst().exp() == 1;
67}
68//}}}
69
70//{{{ int exponent ( const CanonicalForm & f, int q )
71//{{{ docu
72//
73// exponent() - return e > 0 such that x^e == 1 mod f.
74//
75// q: upper limit for e (?)
76//
77//}}}
78int
79exponent ( const CanonicalForm & f, int q )
80{
81    Variable x = f.mvar();
82    int e = 1;
83    CanonicalForm prod = x;
84    while ( e <= q && ! prod.isOne() ) {
85        e++;
86        prod = ( prod * x ) % f;
87    }
88    return e;
89}
90//}}}
91
92//{{{ bool findGenRec ( int d, int n, int q, const CanonicalForm & m, const Variable & x, CanonicalForm & result )
93//{{{ docu
94//
95// findGenRec() - find a generator of GF(q).
96//
97// Returns true iff result is a valid generator.
98//
99// d: degree of extension
100// q: the q in GF(q) (q == p^d)
101// x: generator should be a poly in x
102// n, m: used to step recursively through all polys in FF(p)
103//   Initially, n == d and m == 0.  If 0 <= n <= d we are
104//   in the process of building m, if n < 0 we built m and
105//   may test whether it generates GF(q).
106// result: generator found
107//
108// i: used to step through GF(p)
109// p: current characteristic
110//
111//}}}
112bool
113findGenRec ( int d, int n, int q,
114             const CanonicalForm & m, const Variable & x,
115             CanonicalForm & result )
116{
117    int i, p = getCharacteristic();
118    if ( n < 0 ) {
119        cerr << "."; cerr.flush();
120        // check whether m is irreducible
121        if ( isIrreducible( m ) ) {
122            cerr << "*"; cerr.flush();
123            // check whether m generates multiplicative group
124            if ( exponent( m, q ) == q - 1 ) {
125                result = m;
126                return true;
127            }
128            else
129                return false;
130        }
131        else
132            return false;
133    }
134    // for each monomial x^0, ..., x^n, ..., x^d, try all possible coefficients
135    else  if ( n == d || n == 0 ) {
136        // we want to have a leading coefficient and a constant term,
137        // so start with coefficient >= 1
138        for ( i = 1; i < p; i++ )
139            if ( findGenRec( d, n-1, q, m + i * power( x, n ), x, result ) )
140                return true;
141    }
142    else {
143        for ( i = 0; i < p; i++ )
144            if ( findGenRec( d, n-1, q, m + i * power( x, n ), x, result ) )
145                return true;
146    }
147    return false;
148}
149//}}}
150
151//{{{ CanonicalForm findGen ( int d, int q )
152//{{{ docu
153//
154// findGen() - find and return a generator of GF(q).
155//
156// d: degree of extension
157// q: the q in GF(q)
158//
159//}}}
160CanonicalForm
161findGen ( int d, int q )
162{
163    Variable x( 1 );
164    CanonicalForm result;
165    cerr << "testing p = " << getCharacteristic() << ", d = " << d << " ... ";
166    cerr.flush();
167    bool ok = findGenRec( d, d, q, 0, x, result );
168    cerr << endl;
169    if ( ! ok )
170        return 0;
171    else
172        return result;
173}
174//}}}
175
176//{{{ void printTable ( int d, int q, CanonicalForm mipo )
177//{{{ docu
178//
179// printTable - print +1 table of field GF(q).
180//
181// d: degree of extension
182// q: the q in GF(q)
183// mipo: the minimal polynomial of the extension
184//
185// p: current characteristic
186//
187//}}}
188void
189printTable ( int d, int q, CanonicalForm mipo )
190{
191    int i, p = getCharacteristic();
192
193    // open file to write to
194    ostrstream fname;
195    fname << "gftables/gftable." << p << "." << d << '\0';
196    char * fn = fname.str();
197    ofstream outfile;
198    outfile.open( fn, ios::out );
199    STICKYASSERT1( outfile, "can not open GF(q) table %s for writing", fn );
200    delete fn;
201
202    cerr << "mipo = " << mipo << ": ";
203    cerr << "generating multiplicative group ... ";
204    cerr.flush();
205
206    CanonicalForm * T = new CanonicalForm[maxtable];
207    Variable x( 1 );
208
209    // fill T with powers of x
210    T[0] = 1;
211    for ( i = 1; i < q; i++ )
212        T[i] = ( T[i-1] * x ) % mipo;
213
214    cerr << "generating addition table ... ";
215    cerr.flush();
216
217    // brute force method
218    int * table = new int[maxtable];
219    CanonicalForm f;
220
221    for ( i = 0; i < q; i++ ) {
222        f = T[i] + 1;
223        int j = 0;
224        while ( j < q && T[j] != f ) j++;
225        table[i] = j;
226    }
227
228    cerr << "writing table ... ";
229    cerr.flush();
230
231    outfile << "@@ factory GF(q) table @@" << endl;
232    outfile << p << " " << d << " " << mipo << "; ";
233
234    // print simple reprenstation of mipo
235    outfile << d;
236    CFIterator MiPo = mipo;
237    for ( i = d; MiPo.hasTerms(); i--, MiPo++ ) {
238        int exp;
239        for ( exp = MiPo.exp(); exp < i; i-- )
240            outfile << " 0";
241        outfile << " " << MiPo.coeff();
242    }
243    // since mipo is irreducible, it has a constant term,
244    // so i == 0 at this point
245    outfile << endl;
246
247    int m = gf_tab_numdigits62( q );
248    char * outstr = new char[30*m+1];
249    outstr[30*m] = '\0';
250    i = 1;
251    while ( i < q ) {
252        int k = 0;
253        char * sptr = outstr;
254        while ( i < q && k < 30 ) {
255            convert62( table[i], m, sptr );
256            sptr += m;
257            k++; i++;
258        }
259        while ( k < 30 ) {
260            convert62( 0, m, sptr );
261            sptr += m;
262            k++;
263        }
264        outfile << outstr << endl;
265    }
266    outfile.close();
267
268    delete [] outstr;
269    delete [] T;
270    delete [] table;
271
272    cerr << endl;
273}
274//}}}
275
276int
277main()
278{
279    int i, p, q, n;
280    for ( i = 0; i < primes_len; i++ ) {
281        p = primes[i];
282        q = p*p;
283        n = 2;
284        setCharacteristic( p );
285        while ( q < maxtable ) {
286            CanonicalForm f = findGen( n, q );
287            ASSERT( f != 0, "no generator found" );
288            printTable( n, q, f );
289            n++; q *= p;
290        }
291    }
292}
Note: See TracBrowser for help on using the repository browser.