Skip to content

Commit

Permalink
Improve comments and layout.
Browse files Browse the repository at this point in the history
  • Loading branch information
stevelinton committed Nov 13, 2018
1 parent 7bf4fe3 commit 0dc1377
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 106 deletions.
82 changes: 31 additions & 51 deletions src/finfield.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,46 +8,7 @@
*Y (C) 1998 School Math and Comp. Sci., University of St Andrews, Scotland
*Y Copyright (C) 2002 The GAP Group
**
** This file contains the functions to compute with elements from small
** finite fields.
**
** Finite fields are an important domain in computational group theory
** because the classical matrix groups are defined over those finite fields.
** In GAP we support small finite fields with up to 65536 elements,
** larger fields can be realized as polynomial domains over smaller fields.
**
** Elements in small finite fields are represented as immediate objects.
**
** +----------------+-------------+---+
** | <value> | <field> |010|
** +----------------+-------------+---+
**
** The least significant 3 bits of such an immediate object are always 010,
** flagging the object as an object of a small finite field.
**
** The next 13 bits represent the small finite field where the element lies.
** They are simply an index into a global table of small finite fields.
**
** The most significant 16 bits represent the value of the element.
**
** If the value is 0, then the element is the zero from the finite field.
** Otherwise the integer is the logarithm of this element with respect to a
** fixed generator of the multiplicative group of the finite field plus one.
** In the following desriptions we denote this generator always with $z$, it
** is an element of order $o-1$, where $o$ is the order of the finite field.
** Thus 1 corresponds to $z^{1-1} = z^0 = 1$, i.e., the one from the field.
** Likewise 2 corresponds to $z^{2-1} = z^1 = z$, i.e., the root itself.
**
** This representation makes multiplication very easy, we only have to add
** the values and subtract 1 , because $z^{a-1} * z^{b-1} = z^{(a+b-1)-1}$.
** Addition is reduced to * by the formula $z^a + z^b = z^b * (z^{a-b}+1)$.
** This makes it neccessary to know the successor $z^a + 1$ of every value.
**
** The finite field bag contains the successor for every nonzero value,
** i.e., 'SUCC_FF(<ff>)[<a>]' is the successor of the element <a>, i.e, it
** is the logarithm of $z^{a-1} + 1$. This list is usually called the
** Zech-Logarithm table. The zeroth entry in the finite field bag is the
** order of the finite field minus one.
** The concepts of this kernel module are documented in finfield.h
*/

#include "finfield.h"
Expand All @@ -67,14 +28,38 @@
#include "hpc/aobjects.h"
#endif

Obj SuccFF;
/****************************************************************************
**
*V SuccFF . . . . . Tables for finite fields which are computed on demand
*V TypeFF
*V TypeFF0
**
** SuccFF holds a PLIST of successor lists
** TypeFF holds the types of typical elements of the finite fields
** TypeFF0 holds the types of the zero elements of the finite fields
*/

Obj SuccFF;
Obj TypeFF;
Obj TypeFF0;


/****************************************************************************
**
*V TYPE_FFE . . . . . kernel copy of GAP function TYPE_FFE
*V TYPE_FFE0 . . . . . kernel copy of GAP function TYPE_FFE0
*V TYPE_KERNEL_OBJECT .local copy of GAP variable TYPE_KERNEL_OBJECT used to type
** successor bags
*V PrimitiveRootMod . .local copy of GAP function PrimitiveRootMod, used
** when initializing new fields.
**
** These GAP functions are called to compute types of finite field elemnents
*/

static Obj TYPE_FFE;
static Obj TYPE_FFE0;

static Obj TYPE_KERNEL_OBJECT;
static Obj PrimitiveRootMod;

/****************************************************************************
**
Expand All @@ -90,13 +75,6 @@ static Obj TYPE_FFE0;

#include "finfield_conway.h"


// used for successor bags
static Obj TYPE_KERNEL_OBJECT;

// used to call out to GAP
static Obj PrimitiveRootMod;

/****************************************************************************
**
*F lookupPrimePower ( q ) . . . . . .search for a prime power in tables
Expand Down Expand Up @@ -137,9 +115,11 @@ static FF lookupPrimePower(UInt q)

/****************************************************************************
**
*F FiniteField(<p>,<d>) . . . make the small finite field with <q> elements
*F FiniteFieldBySize( <q>) . .make the small finite field with <q> elements
*F FiniteField(<p>,<d>) . . .make the small finite field with <p>^<d> elements
**
** 'FiniteField' returns the small finite field with <p>^<d> elements.
** The work is done in the lookup function above, and in FiniteFieldBySize
** where the successor tables are computed.
*/

FF FiniteFieldBySize ( UInt q)
Expand Down
86 changes: 31 additions & 55 deletions src/finfield.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,11 @@
**
** Finite fields are an important domain in computational group theory
** because the classical matrix groups are defined over those finite fields.
** In GAP we support small finite fields with up to 65536 elements,
** larger fields can be realized as polynomial domains over smaller fields.
** The GAP kernel supports elements of finite fields up to some fixed size
** limit, typically 2^16 on 32 bit systems and 2^24 on 64 bit systems.
** To change the limits, edit etc/ffgen.c. To access the current limits in the
** kernel, use SIZE_LARGEST_INTERNAL_FF, in GAP use MAXSIZE_GF_INTERNAL.
** Larger fields are supported in the library
**
** Elements in small finite fields are represented as immediate objects.
**
Expand All @@ -25,10 +28,11 @@
** The least significant 3 bits of such an immediate object are always 010,
** flagging the object as an object of a small finite field.
**
** The next 13 bits represent the small finite field where the element lies.
** They are simply an index into a global table of small finite fields.
** The next group of FIELD_BITS_FFE bits represent the small finite field
** where the element lies. They are simply an index into a global table of
** small finite fields, which is constructed at build time.
**
** The most significant 16 bits represent the value of the element.
** The most significant VAL_BITS_FFE bits represent the value of the element.
**
** If the value is 0, then the element is the zero from the finite field.
** Otherwise the integer is the logarithm of this element with respect to a
Expand Down Expand Up @@ -64,10 +68,10 @@
**
** Small finite fields are represented by an index into a global table.
**
** Since there are only 6542 (prime) + 93 (nonprime) small finite fields,
** the index fits into a 'UInt2' (actually into 13 bits).
** Depending on the configuration it may be UInt2 or UInt4. The definition
** is in `ffdata.h` and is calculated by etc/ffgen.c
*/
/* This type is now actually defined in gen/ffdata.h by ffgen*/



/****************************************************************************
Expand Down Expand Up @@ -128,8 +132,8 @@ extern Obj SuccFF;
** 'TYPE_FF' returns the type of elements of the small finite field <ff>.
** 'TYPE_FF0' returns the type of the zero of <ff>
**
** Note that 'TYPE_FF' is a macro, so do not call it with arguments that
** have side effects.
** Note that 'TYPE_FF' and TypeFF0 are macros, so do not call them
** with arguments that have side effects.
*/
#define TYPE_FF(ff) (ELM_PLIST( TypeFF, ff ))
#define TYPE_FF0(ff) (ELM_PLIST( TypeFF0, ff ))
Expand All @@ -148,17 +152,9 @@ extern Obj TypeFF0;
** Values of elements of small finite fields are represented by the
** logarithm of the element with respect to the root plus one.
**
** Since small finite fields contain at most 65536 elements, the value fits
** into a 'UInt2'.
**
** It may be possible to change this to 'UInt4' to allow small finite fields
** with more than than 65536 elements. The macros and have been coded in
** such a way that they work without problems. The exception is 'POW_FFV'
** which will only work if the product of integers of type 'FFV' does not
** cause an overflow. And of course the successor table stored for a finite
** field will become quite large for fields with more than 65536 elements.
** Depending on the configuration, this type may be a UInt2 or UInt4.
** This type is actually defined in gen/ffdata.h ffgen
*/
/* This type is now actually defined in gen/ffdata.h by ffgen*/

/****************************************************************************
**
Expand All @@ -171,11 +167,6 @@ extern Obj TypeFF0;
** the same finite field. If you want to multiply two elements where one
** lies in a subfield of the other use 'ProdFFEFFE'.
**
** Use 'PROD_FFV' only with arguments that are variables or array elements,
** because it is a macro and arguments with side effects will behave strange,
** and because it is a complex macro so most C compilers will be upset by
** complex arguments. Especially do not use 'NEG_FFV(PROD_FFV(a,b,f),f)'.
**
** If one of the values is 0 the product is 0.
** If $a+b <= o$ we have $a * b ~ z^{a-1} * z^{b-1} = z^{(a+b-1)-1} ~ a+b-1$
** otherwise we have $a * b ~ z^{(a+b-2)-(o-1)} = z^{(a+b-o)-1} ~ a+b-o$
Expand Down Expand Up @@ -205,11 +196,6 @@ static inline FFV PROD_FFV(FFV a, FFV b, const FFV *f) {
** the same finite field. If you want to add two elements where one lies in
** a subfield of the other use 'SumFFEFFE'.
**
** Use 'SUM_FFV' only with arguments that are variables or array elements,
** because it is a macro and arguments with side effects will behave strange,
** and because it is a complex macro so most C compilers will be upset by
** complex arguments. Especially do not use 'SUM_FFV(a,NEG_FFV(b,f),f)'.
**
** If either operand is 0, the sum is just the other operand.
** If $a <= b$ we have
** $a + b ~ z^{a-1}+z^{b-1} = z^{a-1} * (z^{(b-1)-(a-1)}+1) ~ a * f[b-a+1]$,
Expand Down Expand Up @@ -241,11 +227,6 @@ static inline FFV SUM_FFV( FFV a, FFV b, const FFV *f) {
** 'NEG_FFV' returns the negative of the finite field value <a> from the
** finite field pointed to by the pointer <f>.
**
** Use 'NEG_FFV' only with arguments that are variables or array elements,
** because it is a macro and arguments with side effects will behave strange,
** and because it is a complex macro so most C compilers will be upset by
** complex arguments. Especially do not use 'NEG_FFV(PROD_FFV(a,b,f),f)'.
**
** If the characteristic is 2, every element is its own additive inverse.
** Otherwise note that $z^{o-1} = 1 = -1^2$ so $z^{(o-1)/2} = 1^{1/2} = -1$.
** If $a <= (o-1)/2$ we have
Expand Down Expand Up @@ -280,10 +261,6 @@ static inline FFV NEG_FFV( FFV a, const FFV *f) {
** the same finite field. If you want to divide two elements where one lies
** in a subfield of the other use 'QuoFFEFFE'.
**
** Use 'QUO_FFV' only with arguments that are variables or array elements,
** because it is a macro and arguments with side effects will behave strange,
** and because it is a complex macro so most C compilers will be upset by
** complex arguments. Especially do not use 'NEG_FFV(PROD_FFV(a,b,f),f)'.
**
** A division by 0 is an error, and dividing 0 by a nonzero value gives 0.
** If $0 <= a-b$ we have $a / b ~ z^{a-1} / z^{b-1} = z^{a-b+1-1} ~ a-b+1$,
Expand All @@ -310,21 +287,16 @@ static inline FFV QUO_FFV(FFV a, FFV b, const FFV *f) {
** the finite field pointed to by the pointer <f>.
**
** Note that 'POW_FFV' may only be used if the right operand is an integer
** in the range $0..order(f)-1$.
** in the range $0..order(f)-1$ (tested by an assertion)
**
** Finally 'POW_FFV' may only be used if the product of two integers of the
** size of 'FFV' does not cause an overflow, i.e. only if 'FFV' is
** 'unsigned short'.
** size of 'FFV' does not cause an overflow. This is tested by a compile
** -time assertion.
**
** Note that 'POW_FFV' is a macro, so do not call it with arguments that
** have side effects.
**
** If the finite field element is 0 the power is also 0, otherwise we have
** $a^n ~ (z^{a-1})^n = z^{(a-1)*n} = z^{(a-1)*n % (o-1)} ~ (a-1)*n % (o-1)$
**
** In the first macro one needs to be careful to convert a and n to UInt4.
** Before performing the multiplication, ANSI-C will only convert to Int
** since UInt2 fits into Int.
*/

static inline FFV POW_FFV(FFV a, UInt n, const FFV *f) {
Expand Down Expand Up @@ -364,9 +336,11 @@ static inline FF FLD_FFE(Obj ffe) {
** and otherwise if <ffe> is $z^i$, it returns $i+1$.
**
*/
static inline FFV VAL_FFE(Obj ffe) {
static inline FFV VAL_FFE(Obj ffe)
{
GAP_ASSERT(IS_FFE(ffe));
return (FFV)((UInt)(ffe) >> (3+FIELD_BITS_FFE)) & ((1 << VAL_BITS_FFE)-1);
return (FFV)((UInt)(ffe) >> (3 + FIELD_BITS_FFE)) &
((1 << VAL_BITS_FFE) - 1);
}

/****************************************************************************
Expand All @@ -378,21 +352,23 @@ return (FFV)((UInt)(ffe) >> (3+FIELD_BITS_FFE)) & ((1 << VAL_BITS_FFE)-1);
**
*/

static inline Obj NEW_FFE(FF fld, FFV val) {
GAP_ASSERT(val < SIZE_FF(fld));
return (Obj) (((UInt)val << (3 + FIELD_BITS_FFE)) | ((UInt)fld << 3) | (UInt) 0x02);
static inline Obj NEW_FFE(FF fld, FFV val)
{
GAP_ASSERT(val < SIZE_FF(fld));
return (Obj)(((UInt)val << (3 + FIELD_BITS_FFE)) | ((UInt)fld << 3) |
(UInt)0x02);
}


/****************************************************************************
**
*F FiniteField(<p>,<d>) . . . make the small finite field with <q> elements
*F FiniteFieldBySize(<q>) . . make the small finite field with <q> elements
**
** 'FiniteField' returns the small finite field with <p>^<d> elements.
*/
extern FF FiniteField (
UInt p,
UInt d );
extern FF FiniteField(UInt p, UInt d);
extern FF FiniteFieldBySize(UInt q);


/****************************************************************************
Expand Down

0 comments on commit 0dc1377

Please sign in to comment.