Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
fingolfin committed Jan 7, 2019
1 parent b42e41c commit 27b0c49
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 43 deletions.
4 changes: 2 additions & 2 deletions doc/ref/fieldfin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -179,8 +179,8 @@ Finally note that elements of large prime fields are stored and
displayed as residue class objects. So
<P/>
<Example><![CDATA[
gap> Z(65537);
ZmodpZObj( 3, 65537 )
gap> Z(NextPrimeInt(2^30));
ZmodpZObj( 2, 1073741827 )
]]></Example>
</Description>
</ManSection>
Expand Down
17 changes: 12 additions & 5 deletions lib/ffe.gd
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
## <ManSection>
## <Func Name="Z" Arg='p^d' Label="for field size"/>
## <Func Name="Z" Arg='p, d' Label="for prime and degree"/>
## <Var Name="MAXSIZE_GF_INTERNAL"/>
##
## <Description>
## For creating elements of a finite field,
Expand All @@ -30,15 +31,20 @@
## <P/>
## &GAP; can represent elements of all finite fields
## <C>GF(<A>p^d</A>)</C> such that either
## (1) <A>p^d</A> <M>&lt;= 65536</M> (in which case an extremely efficient
## internal representation is used);
## (1) <A>p^d</A> <M>&lt;=</M> <C>MAXSIZE_GF_INTERNAL</C> (in which case an
## efficient internal representation is used);
## (2) d = 1, (in which case, for large <A>p</A>, the field is represented
## using the machinery of residue class rings
## (see section&nbsp;<Ref Sect="Residue Class Rings"/>) or
## (3) if the Conway polynomial of degree <A>d</A> over the field with
## <A>p</A> elements is known, or can be computed
## (see <Ref Func="ConwayPolynomial"/>).
## <P/>
##
## <C>MAXSIZE_GF_INTERNAL</C> may depend on the word size of your computer
## and the version of &GAP; but will typically be either <M>2^{16}</M> or
## <M>2^{24}</M>.<P/>
##
## If you attempt to construct an element of <C>GF(<A>p^d</A>)</C> for which
## <A>d</A> <M>> 1</M> and the relevant Conway polynomial is not known,
## and not necessarily easy to find
Expand Down Expand Up @@ -107,14 +113,15 @@
## 0*Z(2)
## gap> a*a;
## Z(2^5)^2
## gap> b := Z(3,12);
## gap> b := Z(3,20);
## z
## gap> b*b;
## z2
## gap> b+b;
## 2z
## gap> Print(b^100,"\n");
## Z(3)^0+Z(3,12)^5+Z(3,12)^6+2*Z(3,12)^8+Z(3,12)^10+Z(3,12)^11
## 2*Z(3,20)^2+Z(3,20)^4+Z(3,20)^6+Z(3,20)^7+2*Z(3,20)^9+2*Z(3,20)^10+2*Z\
## (3,20)^12+2*Z(3,20)^15+2*Z(3,20)^17+Z(3,20)^18+Z(3,20)^19
## ]]></Example>
## <Log><![CDATA[
## gap> Z(11,40);
Expand Down Expand Up @@ -270,7 +277,7 @@ DeclareCategoryCollections( "IsFFECollColl" );
## true
## gap> Z(256) > Z(101);
## false
## gap> Z(2,20) < Z(2,20)^2; # this illustrates the lexicographic ordering
## gap> Z(2,30) < Z(2,30)^2; # this illustrates the lexicographic ordering
## false
## ]]></Example>
## </Description>
Expand Down
22 changes: 11 additions & 11 deletions src/finfield.c
Original file line number Diff line number Diff line change
Expand Up @@ -1443,7 +1443,6 @@ Obj INT_FF (
}



Obj FuncINT_FFE_DEFAULT (
Obj self,
Obj z )
Expand Down Expand Up @@ -1503,10 +1502,10 @@ Obj FuncZ (
FF ff; /* the finite field */

/* check the argument */
if ( (IS_INTOBJ(q) && (INT_INTOBJ(q) > 65536)) ||
(TNUM_OBJ(q) == T_INTPOS))
return CALL_1ARGS(ZOp, q);
if ((IS_INTOBJ(q) && (INT_INTOBJ(q) > MAXSIZE_GF_INTERNAL)) ||
(TNUM_OBJ(q) == T_INTPOS))
return CALL_1ARGS(ZOp, q);

if ( !IS_INTOBJ(q) || INT_INTOBJ(q)<=1 ) {
RequireArgument("Z", q, "must be a positive prime power");
}
Expand All @@ -1521,28 +1520,29 @@ Obj FuncZ (
return NEW_FFE(ff, (q == INTOBJ_INT(2)) ? 1 : 2);
}

Obj FuncZ2 ( Obj self, Obj p, Obj d)
Obj FuncZ2(Obj self, Obj p, Obj d)
{
FF ff;
Int ip, id, id1;
UInt q;
if (ARE_INTOBJS(p, d)) {
ip = INT_INTOBJ(p);
id = INT_INTOBJ(d);
if (ip > 1 && id > 0 && id <= 16 && ip < 65536) {
if (ip > 1 && id > 0 && id <= DEGREE_LARGEST_INTERNAL_FF &&
ip <= MAXSIZE_GF_INTERNAL) {
id1 = id;
q = ip;
while (--id1 > 0 && q <= 65536)
while (--id1 > 0 && q <= MAXSIZE_GF_INTERNAL)
q *= ip;
if (q <= 65536) {
if (q <= MAXSIZE_GF_INTERNAL) {
/* get the finite field */
ff = FiniteField(ip, id);
ff = FiniteFieldBySize(q);

if (ff == 0 || CHAR_FF(ff) != ip)
RequireArgument("Z", p, "must be a prime");

/* make the root */
return NEW_FFE(ff, (ip == 2 && id == 1 ? 1 : 2));
return NEW_FFE(ff, (q == 2) ? 1 : 2);
}
}
}
Expand Down
47 changes: 22 additions & 25 deletions src/finfield.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,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 use
** MAXSIZE_GF_INTERNAL. Support for larger fields is implemented by the
** library
**
** Elements in small finite fields are represented as immediate objects.
**
Expand All @@ -24,10 +27,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,9 @@
**
** 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
*/
typedef UInt2 FF;


/****************************************************************************
Expand Down Expand Up @@ -131,18 +134,9 @@ extern Obj SuccFF;
** 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 by etc/ffgen.c
*/
typedef UInt2 FFV;


/****************************************************************************
**
Expand Down Expand Up @@ -274,11 +268,12 @@ 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.
**
**
** 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)$
Expand Down Expand Up @@ -311,7 +306,7 @@ static inline FFV POW_FFV(FFV a, UInt n, const FFV * f)
static inline FF FLD_FFE(Obj ffe)
{
GAP_ASSERT(IS_FFE(ffe));
return (FF)((((UInt)(ffe)) & 0xFFFF) >> 3);
return (FF)((UInt)(ffe) >> 3) & ((1 << FIELD_BITS_FFE) - 1);
}


Expand All @@ -327,7 +322,8 @@ static inline FF FLD_FFE(Obj ffe)
static inline FFV VAL_FFE(Obj ffe)
{
GAP_ASSERT(IS_FFE(ffe));
return (FFV)(((UInt)(ffe)) >> 16);
return (FFV)((UInt)(ffe) >> (3 + FIELD_BITS_FFE)) &
((1 << VAL_BITS_FFE) - 1);
}


Expand All @@ -342,7 +338,8 @@ static inline FFV VAL_FFE(Obj ffe)
static inline Obj NEW_FFE(FF fld, FFV val)
{
GAP_ASSERT(val < SIZE_FF(fld));
return (Obj)(((UInt)(val) << 16) + ((UInt)(fld) << 3) + (UInt)0x02);
return (Obj)(((UInt)val << (3 + FIELD_BITS_FFE)) | ((UInt)fld << 3) |
(UInt)0x02);
}


Expand Down

0 comments on commit 27b0c49

Please sign in to comment.