From 27b0c49d5a1b74aac4a35d5942b46400422df89b Mon Sep 17 00:00:00 2001 From: Max Horn Date: Fri, 21 Dec 2018 15:00:00 +0100 Subject: [PATCH] WIP --- doc/ref/fieldfin.xml | 4 ++-- lib/ffe.gd | 17 +++++++++++----- src/finfield.c | 22 ++++++++++----------- src/finfield.h | 47 +++++++++++++++++++++----------------------- 4 files changed, 47 insertions(+), 43 deletions(-) diff --git a/doc/ref/fieldfin.xml b/doc/ref/fieldfin.xml index 6f7bd019ffa..f8ce185dc13 100644 --- a/doc/ref/fieldfin.xml +++ b/doc/ref/fieldfin.xml @@ -179,8 +179,8 @@ Finally note that elements of large prime fields are stored and displayed as residue class objects. So

Z(65537); -ZmodpZObj( 3, 65537 ) +gap> Z(NextPrimeInt(2^30)); +ZmodpZObj( 2, 1073741827 ) ]]> diff --git a/lib/ffe.gd b/lib/ffe.gd index 955f0cb3517..7fb75d7a727 100644 --- a/lib/ffe.gd +++ b/lib/ffe.gd @@ -18,6 +18,7 @@ ## ## ## +## ## ## ## For creating elements of a finite field, @@ -30,8 +31,8 @@ ##

## &GAP; can represent elements of all finite fields ## GF(p^d) such that either -## (1) p^d <= 65536 (in which case an extremely efficient -## internal representation is used); +## (1) p^d <= MAXSIZE_GF_INTERNAL (in which case an +## efficient internal representation is used); ## (2) d = 1, (in which case, for large p, the field is represented ## using the machinery of residue class rings ## (see section ) or @@ -39,6 +40,11 @@ ## p elements is known, or can be computed ## (see ). ##

+## +## MAXSIZE_GF_INTERNAL may depend on the word size of your computer +## and the version of &GAP; but will typically be either 2^{16} or +## 2^{24}.

+## ## If you attempt to construct an element of GF(p^d) for which ## d > 1 and the relevant Conway polynomial is not known, ## and not necessarily easy to find @@ -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 ## ]]> ## Z(11,40); @@ -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 ## ]]> ## diff --git a/src/finfield.c b/src/finfield.c index 40b51d46215..50fc6b1a30e 100644 --- a/src/finfield.c +++ b/src/finfield.c @@ -1443,7 +1443,6 @@ Obj INT_FF ( } - Obj FuncINT_FFE_DEFAULT ( Obj self, Obj z ) @@ -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"); } @@ -1521,7 +1520,7 @@ 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; @@ -1529,20 +1528,21 @@ Obj FuncZ2 ( Obj self, Obj p, Obj d) 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); } } } diff --git a/src/finfield.h b/src/finfield.h index ee72418e4c0..bccfc44eeda 100644 --- a/src/finfield.h +++ b/src/finfield.h @@ -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. ** @@ -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 @@ -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; /**************************************************************************** @@ -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; - /**************************************************************************** ** @@ -274,11 +268,12 @@ static inline FFV QUO_FFV(FFV a, FFV b, const FFV * f) ** the finite field pointed to by the pointer . ** ** 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)$ @@ -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); } @@ -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); } @@ -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); }