CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.

| Download

GAP 4.8.9 installation with standard packages -- copy to your CoCalc project to get it

Views: 418346
1
/****************************************************************************
2
**
3
*W finfield.h GAP source Werner Nickel
4
** & Martin Schönert
5
**
6
**
7
*Y Copyright (C) 1996, Lehrstuhl D für Mathematik, RWTH Aachen, Germany
8
*Y (C) 1998 School Math and Comp. Sci., University of St Andrews, Scotland
9
*Y Copyright (C) 2002 The GAP Group
10
**
11
** This file declares the functions to compute with elements from small
12
** finite fields.
13
**
14
** Finite fields are an important domain in computational group theory
15
** because the classical matrix groups are defined over those finite fields.
16
** In GAP we support small finite fields with up to 65536 elements,
17
** larger fields can be realized as polynomial domains over smaller fields.
18
**
19
** Elements in small finite fields are represented as immediate objects.
20
**
21
** +----------------+-------------+---+
22
** | <value> | <field> |010|
23
** +----------------+-------------+---+
24
**
25
** The least significant 3 bits of such an immediate object are always 010,
26
** flagging the object as an object of a small finite field.
27
**
28
** The next 13 bits represent the small finite field where the element lies.
29
** They are simply an index into a global table of small finite fields.
30
**
31
** The most significant 16 bits represent the value of the element.
32
**
33
** If the value is 0, then the element is the zero from the finite field.
34
** Otherwise the integer is the logarithm of this element with respect to a
35
** fixed generator of the multiplicative group of the finite field plus one.
36
** In the following descriptions we denote this generator always with $z$, it
37
** is an element of order $o-1$, where $o$ is the order of the finite field.
38
** Thus 1 corresponds to $z^{1-1} = z^0 = 1$, i.e., the one from the field.
39
** Likewise 2 corresponds to $z^{2-1} = z^1 = z$, i.e., the root itself.
40
**
41
** This representation makes multiplication very easy, we only have to add
42
** the values and subtract 1 , because $z^{a-1} * z^{b-1} = z^{(a+b-1)-1}$.
43
** Addition is reduced to * by the formula $z^a + z^b = z^b * (z^{a-b}+1)$.
44
** This makes it necessary to know the successor $z^a + 1$ of every value.
45
**
46
** The finite field bag contains the successor for every nonzero value,
47
** i.e., 'SUCC_FF(<ff>)[<a>]' is the successor of the element <a>, i.e, it
48
** is the logarithm of $z^{a-1} + 1$. This list is usually called the
49
** Zech-Logarithm table. The zeroth entry in the finite field bag is the
50
** order of the finite field minus one.
51
*/
52
53
#ifndef GAP_FINFIELD_H
54
#define GAP_FINFIELD_H
55
56
57
/****************************************************************************
58
**
59
*T FF . . . . . . . . . . . . . . . . . . . . . type of small finite fields
60
**
61
** 'FF' is the type used to represent small finite fields.
62
**
63
** Small finite fields are represented by an index into a global table.
64
**
65
** Since there are only 6542 (prime) + 93 (nonprime) small finite fields,
66
** the index fits into a 'UInt2' (actually into 13 bits).
67
*/
68
typedef UInt2 FF;
69
70
71
/****************************************************************************
72
**
73
*F CHAR_FF(<ff>) . . . . . . . . . . . characteristic of small finite field
74
**
75
** 'CHAR_FF' returns the characteristic of the small finite field <ff>.
76
**
77
** Note that 'CHAR_FF' is a macro, so do not call it with arguments that
78
** have side effects.
79
*/
80
#define CHAR_FF(ff) INT_INTOBJ( ELM_PLIST( CharFF, ff ) )
81
82
extern Obj CharFF;
83
84
85
/****************************************************************************
86
**
87
*F DEGR_FF(<ff>) . . . . . . . . . . . . . . . degree of small finite field
88
**
89
** 'DEGR_FF' returns the degree of the small finite field <ff>.
90
**
91
** Note that 'DEGR_FF' is a macro, so do not call it with arguments that
92
** have side effects.
93
*/
94
#define DEGR_FF(ff) INT_INTOBJ( ELM_PLIST( DegrFF, ff ) )
95
96
extern Obj DegrFF;
97
98
99
/****************************************************************************
100
**
101
*F SIZE_FF(<ff>) . . . . . . . . . . . . . . . . size of small finite field
102
**
103
** 'SIZE_FF' returns the size of the small finite field <ff>.
104
**
105
** Note that 'SIZE_FF' is a macro, so do not call it with arguments that
106
** have side effects.
107
*/
108
#define SIZE_FF(ff) (*SUCC_FF(ff)+1)
109
110
111
/****************************************************************************
112
**
113
*F SUCC_FF(<ff>) . . . . . . . . . . . successor table of small finite field
114
**
115
** 'SUCC_FF' returns a pointer to the successor table of the small finite
116
** field <ff>.
117
**
118
** Note that 'SUCC_FF' is a macro, so do not call it with arguments that
119
** side effects.
120
*/
121
#define SUCC_FF(ff) ((FFV*)ADDR_OBJ( ELM_PLIST( SuccFF, ff ) ))
122
123
extern Obj SuccFF;
124
125
126
/****************************************************************************
127
**
128
*F TYPE_FF(<ff>) . . . . . . . . . . . . . . . type of a small finite field
129
**
130
** 'TYPE_FF' returns the type of elements of the small finite field <ff>.
131
** 'TYPE_FF0' returns the type of the zero of <ff>
132
**
133
** Note that 'TYPE_FF' is a macro, so do not call it with arguments that
134
** have side effects.
135
*/
136
#define TYPE_FF(ff) (ELM_PLIST( TypeFF, ff ))
137
#define TYPE_FF0(ff) (ELM_PLIST( TypeFF0, ff ))
138
139
extern Obj TypeFF;
140
extern Obj TypeFF0;
141
142
extern Obj TYPE_FFE;
143
extern Obj TYPE_FFE0;
144
145
146
/****************************************************************************
147
**
148
*T FFV . . . . . . . . type of the values of elements of small finite fields
149
**
150
** 'FFV' is the type used to represent the values of elements of small
151
** finite fields.
152
**
153
** Values of elements of small finite fields are represented by the
154
** logarithm of the element with respect to the root plus one.
155
**
156
** Since small finite fields contain at most 65536 elements, the value fits
157
** into a 'UInt2'.
158
**
159
** It may be possible to change this to 'UInt4' to allow small finite fields
160
** with more than than 65536 elements. The macros and have been coded in
161
** such a way that they work without problems. The exception is 'POW_FFV'
162
** which will only work if the product of integers of type 'FFV' does not
163
** cause an overflow. And of course the successor table stored for a finite
164
** field will become quite large for fields with more than 65536 elements.
165
*/
166
typedef UInt2 FFV;
167
168
169
/****************************************************************************
170
**
171
*F SUM_FFV(<a>,<b>,<f>) . . . . . . . . . . . . sum of finite field values
172
**
173
** 'SUM_FFV' returns the sum of the two finite field values <a> and <b> from
174
** the finite field pointed to by the pointer <f>.
175
**
176
** Note that 'SUM_FFV' may only be used if the operands are represented in
177
** the same finite field. If you want to add two elements where one lies in
178
** a subfield of the other use 'SumFFEFFE'.
179
**
180
** Use 'SUM_FFV' only with arguments that are variables or array elements,
181
** because it is a macro and arguments with side effects will behave strange,
182
** and because it is a complex macro so most C compilers will be upset by
183
** complex arguments. Especially do not use 'SUM_FFV(a,NEG_FFV(b,f),f)'.
184
**
185
** If either operand is 0, the sum is just the other operand.
186
** If $a <= b$ we have
187
** $a + b ~ z^{a-1}+z^{b-1} = z^{a-1} * (z^{(b-1)-(a-1)}+1) ~ a * f[b-a+1]$,
188
** otherwise we have
189
** $a + b ~ z^{b-1}+z^{a-1} = z^{b-1} * (z^{(a-1)-(b-1)}+1) ~ b * f[a-b+1]$.
190
*/
191
#define SUM2_FFV(a,b,f) PROD_FFV( a, (f)[(b)-(a)+1], f )
192
#define SUM1_FFV(a,b,f) ( (a)<=(b) ? SUM2_FFV(a,b,f) : SUM2_FFV(b,a,f) )
193
#define SUM_FFV(a,b,f) ( (a)==0 || (b)==0 ? (a)+(b) : SUM1_FFV(a,b,f) )
194
195
196
/****************************************************************************
197
**
198
*F NEG_FFV(<a>,<f>) . . . . . . . . . . . . negative of finite field value
199
**
200
** 'NEG_FFV' returns the negative of the finite field value <a> from the
201
** finite field pointed to by the pointer <f>.
202
**
203
** Use 'NEG_FFV' only with arguments that are variables or array elements,
204
** because it is a macro and arguments with side effects will behave strange,
205
** and because it is a complex macro so most C compilers will be upset by
206
** complex arguments. Especially do not use 'NEG_FFV(PROD_FFV(a,b,f),f)'.
207
**
208
** If the characteristic is 2, every element is its own additive inverse.
209
** Otherwise note that $z^{o-1} = 1 = -1^2$ so $z^{(o-1)/2} = 1^{1/2} = -1$.
210
** If $a <= (o-1)/2$ we have
211
** $-a ~ -1 * z^{a-1} = z^{(o-1)/2} * z^{a-1} = z^{a+(o-1)/2-1} ~ a+(o-1)/2$
212
** otherwise we have
213
** $-a ~ -1 * z^{a-1} = z^{a+(o-1)/2-1} = z^{a+(o-1)/2-1-(o-1)} ~ a-(o-1)/2$
214
*/
215
#define NEG2_FFV(a,f) ( (a)<=*(f)/2 ? (a)+*(f)/2 : (a)-*(f)/2 )
216
#define NEG1_FFV(a,f) ( *(f)%2==1 ? (a) : NEG2_FFV(a,f) )
217
#define NEG_FFV(a,f) ( (a)==0 ? 0 : NEG1_FFV(a,f) )
218
219
220
/****************************************************************************
221
**
222
*F PROD_FFV(<a>,<b>,<f>) . . . . . . . . . . . product of finite field value
223
**
224
** 'PROD_FFV' returns the product of the two finite field values <a> and <b>
225
** from the finite field pointed to by the pointer <f>.
226
**
227
** Note that 'PROD_FFV' may only be used if the operands are represented in
228
** the same finite field. If you want to multiply two elements where one
229
** lies in a subfield of the other use 'ProdFFEFFE'.
230
**
231
** Use 'PROD_FFV' only with arguments that are variables or array elements,
232
** because it is a macro and arguments with side effects will behave strange,
233
** and because it is a complex macro so most C compilers will be upset by
234
** complex arguments. Especially do not use 'NEG_FFV(PROD_FFV(a,b,f),f)'.
235
**
236
** If one of the values is 0 the product is 0.
237
** If $a+b <= o$ we have $a * b ~ z^{a-1} * z^{b-1} = z^{(a+b-1)-1} ~ a+b-1$
238
** otherwise we have $a * b ~ z^{(a+b-2)-(o-1)} = z^{(a+b-o)-1} ~ a+b-o$
239
*/
240
#define PROD1_FFV(a,b,f) ( (a)-1<=*(f)-(b) ? (a)-1+(b) : (a)-1-(*(f)-(b)) )
241
#define PROD_FFV(a,b,f) ( (a)==0 || (b)==0 ? 0 : PROD1_FFV(a,b,f) )
242
243
244
/****************************************************************************
245
**
246
*F QUO_FFV(<a>,<b>,<f>) . . . . . . . . . . quotient of finite field values
247
**
248
** 'QUO_FFV' returns the quotient of the two finite field values <a> and <b>
249
** from the finite field pointed to by the pointer <f>.
250
**
251
** Note that 'QUO_FFV' may only be used if the operands are represented in
252
** the same finite field. If you want to divide two elements where one lies
253
** in a subfield of the other use 'QuoFFEFFE'.
254
**
255
** Use 'QUO_FFV' only with arguments that are variables or array elements,
256
** because it is a macro and arguments with side effects will behave strange,
257
** and because it is a complex macro so most C compilers will be upset by
258
** complex arguments. Especially do not use 'NEG_FFV(PROD_FFV(a,b,f),f)'.
259
**
260
** A division by 0 is an error, and dividing 0 by a nonzero value gives 0.
261
** If $0 <= a-b$ we have $a / b ~ z^{a-1} / z^{b-1} = z^{a-b+1-1} ~ a-b+1$,
262
** otherwise we have $a / b ~ z^{a-b+1-1} = z^{a-b+(o-1)} ~ a-b+o$.
263
*/
264
#define QUO1_FFV(a,b,f) ( (b)<=(a) ? (a)-(b)+1 : *(f)-(b)+1+(a) )
265
#define QUO_FFV(a,b,f) ( (a)==0 ? 0 : QUO1_FFV(a,b,f) )
266
267
268
/****************************************************************************
269
**
270
*F POW_FFV(<a>,<n>,<f>) . . . . . . . . . . . power of a finite field value
271
**
272
** 'POW_FFV' returns the <n>th power of the finite field value <a> from the
273
** the finite field pointed to by the pointer <f>.
274
**
275
** Note that 'POW_FFV' may only be used if the right operand is an integer
276
** in the range $0..order(f)-1$.
277
**
278
** Finally 'POW_FFV' may only be used if the product of two integers of the
279
** size of 'FFV' does not cause an overflow, i.e. only if 'FFV' is
280
** 'unsigned short'.
281
**
282
** Note that 'POW_FFV' is a macro, so do not call it with arguments that
283
** have side effects. For optimal performance put the operands in registers
284
** before calling 'POW_FFV'.
285
**
286
** If the finite field element is 0 the power is also 0, otherwise we have
287
** $a^n ~ (z^{a-1})^n = z^{(a-1)*n} = z^{(a-1)*n % (o-1)} ~ (a-1)*n % (o-1)$
288
**
289
** In the first macro one needs to be careful to convert a and n to UInt4.
290
** Before performing the multiplication, ANSI-C will only convert to Int
291
** since UInt2 fits into Int.
292
*/
293
#define POW1_FFV(a,n,f) ( (((UInt4)(a)-1) * (UInt4)(n)) % (UInt4)*(f) + 1 )
294
#define POW_FFV(a,n,f) ( (n)==0 ? 1 : ( (a)==0 ? 0 : POW1_FFV(a,n,f) ) )
295
296
297
/****************************************************************************
298
**
299
*F FLD_FFE(<ffe>) . . . . . . . field of an element of a small finite field
300
**
301
** 'FLD_FFE' returns the small finite field over which the element <ffe> is
302
** represented.
303
**
304
** Note that 'FLD_FFE' is a macro, so do not call it with arguments that
305
** have side effects.
306
*/
307
#define FLD_FFE(ffe) ((FF)((((UInt)(ffe)) & 0xFFFF) >> 3))
308
309
310
/****************************************************************************
311
**
312
*F VAL_FFE(<ffe>) . . . . . . . value of an element of a small finite field
313
**
314
** 'VAL_FFE' returns the value of the element <ffe> of a small finite field.
315
** Thus, if <ffe> is $0_F$, it returns 0; if <ffe> is $1_F$, it returns 1;
316
** and otherwise if <ffe> is $z^i$, it returns $i+1$.
317
**
318
** Note that 'VAL_FFE' is a macro, so do not call it with arguments that
319
** have side effects.
320
*/
321
#define VAL_FFE(ffe) ((FFV)(((UInt)(ffe)) >> 16))
322
323
324
/****************************************************************************
325
**
326
*F NEW_FFE(<fld>,<val>) . . . . make a new element of a small finite field
327
**
328
** 'NEW_FFE' returns a new element <ffe> of the small finite field <fld>
329
** with the value <val>.
330
**
331
** Note that 'NEW_FFE' is a macro, so do not call it with arguments that
332
** have side effects.
333
*/
334
#define NEW_FFE(fld,val) ((Obj)(((UInt)(val) << 16) + \
335
((UInt)(fld) << 3) + (UInt)0x02))
336
337
338
/****************************************************************************
339
**
340
*F FiniteField(<p>,<d>) . . . make the small finite field with <q> elements
341
**
342
** 'FiniteField' returns the small finite field with <p>^<d> elements.
343
*/
344
extern FF FiniteField (
345
UInt p,
346
UInt d );
347
348
349
/****************************************************************************
350
**
351
*F CommonFF(<f1>,<d1>,<f2>,<d2>) . . . . . . . . . . . . find a common field
352
**
353
** 'CommonFF' returns a small finite field that can represent elements of
354
** degree <d1> from the small finite field <f1> and elements of degree <d2>
355
** from the small finite field <f2>. Note that this is not guaranteed to be
356
** the smallest such field. If <f1> and <f2> have different characteristic
357
** or the smallest common field, is too large, 'CommonFF' returns 0.
358
*/
359
extern FF CommonFF (
360
FF f1,
361
UInt d1,
362
FF f2,
363
UInt d2 );
364
365
366
/****************************************************************************
367
**
368
*F CharFFE(<ffe>) . . . . . . . . . characteristic of a small finite field
369
**
370
** 'CharFFE' returns the characteristic of the small finite field in which
371
** the element <ffe> lies.
372
*/
373
extern UInt CharFFE (
374
Obj ffe );
375
376
377
/****************************************************************************
378
**
379
*F DegreeFFE(<ffe>) . . . . . . . . . . . . degree of a small finite field
380
**
381
** 'DegreeFFE' returns the degree of the smallest finite field in which the
382
** element <ffe> lies.
383
*/
384
extern UInt DegreeFFE (
385
Obj ffe );
386
387
388
/****************************************************************************
389
**
390
*F TypeFFE(<ffe>) . . . . . . . . . . type of element of small finite field
391
**
392
** 'TypeFFE' returns the type of the element <ffe> of a small finite field.
393
**
394
** 'TypeFFE' is the function in 'TypeObjFuncs' for elements in small finite
395
** fields.
396
*/
397
extern Obj TypeFFE (
398
Obj ffe );
399
400
401
/****************************************************************************
402
**
403
404
*F * * * * * * * * * * * * * initialize package * * * * * * * * * * * * * * *
405
*/
406
407
408
/****************************************************************************
409
**
410
411
*F InitInfoFinfield() . . . . . . . . . . . . . . . table of init functions
412
*/
413
StructInitInfo * InitInfoFinfield ( void );
414
415
416
#endif // GAP_FINFIELD_H
417
418
/****************************************************************************
419
**
420
421
*E finfield.h . . . . . . . . . . . . . . . . . . . . . . . . . . ends here
422
*/
423
424