FF FiniteFieldBySize(UInt q)
{
FF ff; // finite field, result
Obj tmp; // temporary bag
Obj succBag; // successor table bag
FFV * succ; // successor table
FFV * indx; // index table
UInt p; // characteristic of the field
UInt poly; // Conway polynomial of extension
UInt i, l, f, n, e; // loop variables
Obj root; // will be a primitive root mod p
// determine the characteristic of the field
p = CHAR_FF(ff);
// allocate a bag for the successor table and one for a temporary
tmp = NewKernelBuffer(sizeof(Obj) + q * sizeof(FFV));
succBag = NewKernelBuffer(sizeof(Obj) + q * sizeof(FFV));
// if q is a prime find the smallest primitive root $e$, use $x - e$
if (DEGR_FF(ff) == 1) { if (p < 65537) { /* for smaller primes we do this in the kernel for performance and bootstrappingreasons
TODO -- review the threshold */ for (e = 1, i = 1; i != p - 1; ++e) { for (f = e, i = 1; f != 1; ++i)
f = (f * e) % p;
}
} else { // Otherwise we ask the library
root = CALL_1ARGS(PrimitiveRootMod, INTOBJ_INT(p));
e = INT_INTOBJ(root) + 1;
}
poly = p - (e - 1);
}
// otherwise look up the polynomial used to construct this field else { for (i = 0; PolsFF[i] != q; i += 2)
;
poly = PolsFF[i + 1];
}
// construct 'indx' such that 'e = x^(indx[e]-1) % poly' for every e
indx[0] = 0; for (e = 1, n = 0; n < q - 1; ++n) {
indx[e] = n + 1; // e =p*e mod poly =x*e mod poly =x*x^n mod poly =x^{n+1} mod poly if (p != 2) {
f = p * (e % (q / p));
l = ((p - 1) * (e / (q / p))) % p;
e = 0; for (i = 1; i < q; i *= p)
e = e + i * ((f / i + l * (poly / i)) % p);
} else { if (2 * e & q)
e = 2 * e ^ poly ^ q; else
e = 2 * e;
}
}
// construct 'succ' such that 'x^(n-1)+1 = x^(succ[n]-1)' for every n
succ[0] = q - 1; for (e = 1, f = p - 1; e < q; e++) { if (e < f) {
succ[indx[e]] = indx[e + 1];
} else {
succ[indx[e]] = indx[e + 1 - p];
f += p;
}
}
/**************************************************************************** ** *FDegreeFFE(<ffe>)............degreeofasmallfinitefield ** **'DegreeFFE'returnsthedegreeofthesmallestfinitefieldinwhichthe **element<ffe>lies.
*/
UInt DegreeFFE (
Obj ffe )
{
UInt d; // degree, result
FFV val; // value of element
FF fld; // field of element
UInt q; // size of field
UInt p; // char. of field
UInt m; // size of minimal field
// get the value, the field, the size, and the characteristic
val = VAL_FFE( ffe );
fld = FLD_FFE( ffe );
q = SIZE_FF( fld );
p = CHAR_FF( fld );
// the zero element has a degree of one if ( val == 0 ) { return1;
}
// compute the degree
m = p;
d = 1; while ( (q-1) % (m-1) != 0 || (val-1) % ((q-1)/(m-1)) != 0 ) {
m *= p;
d += 1;
}
/**************************************************************************** ** *FEqFFE(<opL>,<opR>).......testiffinitefieldelementsareequal ** **'EqFFE'returns'True'ifthetwofinitefieldelements<opL>and<opR> **areequaland'False'othwise. ** **Thisiscomplicatedbecauseitmustaccountforthefollowingsituation. **Suppose'a'is'Z(3)','b'is'Z(3^2)^4'andfinally'c'is'Z(3^3)^13'. **Mathematically'a'isequalto'b',sowewant'a=b'tobe'true'and **since'a'isrepresentedoverasubfieldof'b'thisisnobigproblem. **Again'a'isequalto'c',andagainwewant'a=c'tobe'true'and **againthisisnoproblemsince'a'isrepresentedoverasubfieldof'c'. **Since'='oughttobetransitivewealsowant'b=c'tobe'true'and **thisisaproblem,becausetheyarerepresentedoverincompatiblefields.
*/ staticInt EqFFE(Obj opL, Obj opR)
{
FFV vL, vR; // value of left and right
FF fL, fR; // field of left and right
UInt pL, pR; // char. of left and right
UInt qL, qR; // size of left and right
UInt mL, mR; // size of minimal field
// get the values and the fields over which they are represented
vL = VAL_FFE( opL );
vR = VAL_FFE( opR );
fL = FLD_FFE( opL );
fR = FLD_FFE( opR );
// if the elements are represented over the same field, it is easy if ( fL == fR ) { return (vL == vR);
}
// elements in fields of different characteristic are different too
pL = CHAR_FF( fL );
pR = CHAR_FF( fR ); if ( pL != pR ) { return0;
}
// the zero element is not equal to any other element if ( vL == 0 || vR == 0 ) { return (vL == 0 && vR == 0);
}
// compute the sizes of the minimal fields in which the elements lie
qL = SIZE_FF( fL );
mL = pL; while ( (qL-1) % (mL-1) != 0 || (vL-1) % ((qL-1)/(mL-1)) != 0 ) mL *= pL;
qR = SIZE_FF( fR );
mR = pR; while ( (qR-1) % (mR-1) != 0 || (vR-1) % ((qR-1)/(mR-1)) != 0 ) mR *= pR;
// elements in different fields are different too if ( mL != mR ) { return0;
}
// otherwise compare the elements in the common minimal field return ((vL-1)/((qL-1)/(mL-1)) == (vR-1)/((qR-1)/(mR-1)));
}
/**************************************************************************** ** *FLtFFE(<opL>,<opR>)......testiffinitefieldelementsissmaller ** **'LtFFEFFE'returns'True'ifthefinitefieldelement<opL>isstrictly **lessthanthefinitefieldelement<opR>and'False'otherwise.
*/ staticInt LtFFE(Obj opL, Obj opR)
{
FFV vL, vR; // value of left and right
FF fL, fR; // field of left and right
UInt pL, pR; // char. of left and right
UInt qL, qR; // size of left and right
UInt mL, mR; // size of minimal field
// get the values and the fields over which they are represented
vL = VAL_FFE( opL );
vR = VAL_FFE( opR );
fL = FLD_FFE( opL );
fR = FLD_FFE( opR );
// elements in fields of different characteristic are not comparable
pL = CHAR_FF( fL );
pR = CHAR_FF( fR ); if ( pL != pR ) { return (DoOperation2Args( LtOper, opL, opR ) == True);
}
// the zero element is smaller than any other element if ( vL == 0 || vR == 0 ) { return (vL == 0 && vR != 0);
}
// get the sizes of the fields over which the elements are written
qL = SIZE_FF( fL );
qR = SIZE_FF( fR );
// Deal quickly with the case where both elements are written over the ground field if (qL ==pL && qR == pR) return vL < vR;
// compute the sizes of the minimal fields in which the elements lie
mL = pL; while ( (qL-1) % (mL-1) != 0 || (vL-1) % ((qL-1)/(mL-1)) != 0 ) mL *= pL;
mR = pR; while ( (qR-1) % (mR-1) != 0 || (vR-1) % ((qR-1)/(mR-1)) != 0 ) mR *= pR;
// elements in smaller fields are smaller too if ( mL != mR ) { return (mL < mR);
}
// otherwise compare the elements in the common minimal field return ((vL-1)/((qL-1)/(mL-1)) < (vR-1)/((qR-1)/(mR-1)));
}
/**************************************************************************** ** *FPrFFV(<fld>,<val>).............printafinitefieldvalue ** **'PrFFV'printsthevalue<val>fromthefinitefield<fld>. **
*/ staticvoid PrFFV(FF fld, FFV val)
{
UInt q; // size of finite field
UInt p; // char. of finite field
UInt m; // size of minimal field
UInt d; // degree of minimal field
// get the characteristic, order of the minimal field and the degree
q = SIZE_FF( fld );
p = CHAR_FF( fld );
// print the zero if ( val == 0 ) {
Pr("%>0*Z(%>%d%2<)", (Int)p, 0);
}
// print a nonzero element as power of the primitive root else {
// find the degree of the minimal field in that the element lies
d = 1; m = p; while ( (q-1) % (m-1) != 0 || (val-1) % ((q-1)/(m-1)) != 0 ) {
d++; m *= p;
}
val = (val-1) / ((q-1)/(m-1)) + 1;
// print the element
Pr("%>Z(%>%d%<", (Int)p, 0); if ( d == 1 ) {
Pr("%<)", 0, 0);
} else {
Pr("^%>%d%2<)", (Int)d, 0);
} if ( val != 2 ) {
Pr("^%>%d%<", (Int)(val-1), 0);
}
}
static Obj SumFFEFFE(Obj opL, Obj opR)
{
FFV vL, vR, vX; // value of left, right, result
FF fL, fR, fX; // field of left, right, result
UInt qL, qR, qX; // size of left, right, result
// get the values, handle trivial cases
vL = VAL_FFE( opL );
vR = VAL_FFE( opR );
// bring the two operands into a common field <fX>
fL = FLD_FFE( opL );
qL = SIZE_FF( fL );
fR = FLD_FFE( opR );
qR = SIZE_FF( fR );
if ( qL == qR ) {
fX = fL;
} elseif ( qL % qR == 0 && (qL-1) % (qR-1) == 0 ) {
fX = fL; if ( vR != 0 ) vR = (qL-1) / (qR-1) * (vR-1) + 1;
} elseif ( qR % qL == 0 && (qR-1) % (qL-1) == 0 ) {
fX = fR; if ( vL != 0 ) vL = (qR-1) / (qL-1) * (vL-1) + 1;
} else {
fX = CommonFF( fL, DegreeFFE(opL), fR, DegreeFFE(opR) ); if ( fX == 0 ) return CALL_2ARGS( SUM_FFE_LARGE, opL, opR );
qX = SIZE_FF( fX ); // if ( vL != 0 ) vL = (qX-1) / (qL-1) * (vL-1) + 1; if ( vL != 0 ) vL = ((qX-1) * (vL-1)) / (qL-1) + 1; // if ( vR != 0 ) vR = (qX-1) / (qR-1) * (vR-1) + 1; if ( vR != 0 ) vR = ((qX-1) * (vR-1)) / (qR-1) + 1;
}
static Obj SumFFEInt(Obj opL, Obj opR)
{
FFV vL, vR, vX; // value of left, right, result
FF fX; // field of result Int pX; // char. of result const FFV* sX; // successor table of result field
// get the field for the result
fX = FLD_FFE( opL );
pX = CHAR_FF( fX );
sX = SUCC_FF( fX );
// get the right operand
vX = ((INT_INTOBJ( opR ) % pX) + pX) % pX; if ( vX == 0 ) {
vR = 0;
} else {
vR = 1; for ( ; 1 < vX; vX-- ) vR = sX[vR];
}
static Obj SumIntFFE(Obj opL, Obj opR)
{
FFV vL, vR, vX; // value of left, right, result
FF fX; // field of result Int pX; // char. of result const FFV* sX; // successor table of result field
// get the field for the result
fX = FLD_FFE( opR );
pX = CHAR_FF( fX );
sX = SUCC_FF( fX );
// get the left operand
vX = ((INT_INTOBJ( opL ) % pX) + pX) % pX; if ( vX == 0 ) {
vL = 0;
} else {
vL = 1; for ( ; 1 < vX; vX-- ) vL = sX[vL];
}
/**************************************************************************** ** *FZeroFFE(<op>)..............zeroofafinitefieldelement
*/ static Obj ZeroFFE(Obj op)
{
FF fX; // field of result
// get the field for the result
fX = FLD_FFE( op );
return NEW_FFE( fX, 0 );
}
/**************************************************************************** ** *FAInvFFE(<op>)..........additiveinverseoffinitefieldelement
*/ static Obj AInvFFE(Obj op)
{
FFV v, vX; // value of operand, result
FF fX; // field of result const FFV* sX; // successor table of result field
// get the field for the result
fX = FLD_FFE( op );
sX = SUCC_FF( fX );
static Obj DiffFFEFFE(Obj opL, Obj opR)
{
FFV vL, vR, vX; // value of left, right, result
FF fL, fR, fX; // field of left, right, result
UInt qL, qR, qX; // size of left, right, result
// get the values, handle trivial cases
vL = VAL_FFE( opL );
vR = VAL_FFE( opR );
// bring the two operands into a common field <fX>
fL = FLD_FFE( opL );
qL = SIZE_FF( fL );
fR = FLD_FFE( opR );
qR = SIZE_FF( fR );
if ( qL == qR ) {
fX = fL;
} elseif ( qL % qR == 0 && (qL-1) % (qR-1) == 0 ) {
fX = fL; if ( vR != 0 ) vR = (qL-1) / (qR-1) * (vR-1) + 1;
} elseif ( qR % qL == 0 && (qR-1) % (qL-1) == 0 ) {
fX = fR; if ( vL != 0 ) vL = (qR-1) / (qL-1) * (vL-1) + 1;
} else {
fX = CommonFF( fL, DegreeFFE(opL), fR, DegreeFFE(opR) ); if ( fX == 0 ) return CALL_2ARGS( DIFF_FFE_LARGE, opL, opR );
qX = SIZE_FF( fX ); // if ( vL != 0 ) vL = (qX-1) / (qL-1) * (vL-1) + 1; if ( vL != 0 ) vL = ((qX-1) * (vL-1)) / (qL-1) + 1; // if ( vR != 0 ) vR = (qX-1) / (qR-1) * (vR-1) + 1; if ( vR != 0 ) vR = ((qX-1) * (vR-1)) / (qR-1) + 1;
}
static Obj DiffFFEInt(Obj opL, Obj opR)
{
FFV vL, vR, vX; // value of left, right, result
FF fX; // field of result Int pX; // char. of result const FFV* sX; // successor table of result field
// get the field for the result
fX = FLD_FFE( opL );
pX = CHAR_FF( fX );
sX = SUCC_FF( fX );
// get the right operand
vX = ((INT_INTOBJ( opR ) % pX) + pX) % pX; if ( vX == 0 ) {
vR = 0;
} else {
vR = 1; for ( ; 1 < vX; vX-- ) vR = sX[vR];
}
static Obj DiffIntFFE(Obj opL, Obj opR)
{
FFV vL, vR, vX; // value of left, right, result
FF fX; // field of result Int pX; // char. of result const FFV* sX; // successor table of result field
// get the field for the result
fX = FLD_FFE( opR );
pX = CHAR_FF( fX );
sX = SUCC_FF( fX );
// get the left operand
vX = ((INT_INTOBJ( opL ) % pX) + pX) % pX; if ( vX == 0 ) {
vL = 0;
} else {
vL = 1; for ( ; 1 < vX; vX-- ) vL = sX[vL];
}
static Obj ProdFFEFFE(Obj opL, Obj opR)
{
FFV vL, vR, vX; // value of left, right, result
FF fL, fR, fX; // field of left, right, result
UInt qL, qR, qX; // size of left, right, result
// get the values, handle trivial cases
vL = VAL_FFE( opL );
vR = VAL_FFE( opR );
// bring the two operands into a common field <fX>
fL = FLD_FFE( opL );
qL = SIZE_FF( fL );
fR = FLD_FFE( opR );
qR = SIZE_FF( fR );
if ( qL == qR ) {
fX = fL;
} elseif ( qL % qR == 0 && (qL-1) % (qR-1) == 0 ) {
fX = fL; if ( vR != 0 ) vR = (qL-1) / (qR-1) * (vR-1) + 1;
} elseif ( qR % qL == 0 && (qR-1) % (qL-1) == 0 ) {
fX = fR; if ( vL != 0 ) vL = (qR-1) / (qL-1) * (vL-1) + 1;
} else {
fX = CommonFF( fL, DegreeFFE(opL), fR, DegreeFFE(opR) ); if ( fX == 0 ) return CALL_2ARGS( PROD_FFE_LARGE, opL, opR );
qX = SIZE_FF( fX ); // if ( vL != 0 ) vL = (qX-1) / (qL-1) * (vL-1) + 1; if ( vL != 0 ) vL = ((qX-1) * (vL-1)) / (qL-1) + 1; // if ( vR != 0 ) vR = (qX-1) / (qR-1) * (vR-1) + 1; if ( vR != 0 ) vR = ((qX-1) * (vR-1)) / (qR-1) + 1;
}
static Obj ProdFFEInt(Obj opL, Obj opR)
{
FFV vL, vR, vX; // value of left, right, result
FF fX; // field of result Int pX; // char. of result const FFV* sX; // successor table of result field
// get the field for the result
fX = FLD_FFE( opL );
pX = CHAR_FF( fX );
sX = SUCC_FF( fX );
// get the right operand
vX = ((INT_INTOBJ( opR ) % pX) + pX) % pX; if ( vX == 0 ) {
vR = 0;
} else {
vR = 1; for ( ; 1 < vX; vX-- ) vR = sX[vR];
}
static Obj ProdIntFFE(Obj opL, Obj opR)
{
FFV vL, vR, vX; // value of left, right, result
FF fX; // field of result Int pX; // char. of result const FFV* sX; // successor table of result field
// get the field for the result
fX = FLD_FFE( opR );
pX = CHAR_FF( fX );
sX = SUCC_FF( fX );
// get the left operand
vX = ((INT_INTOBJ( opL ) % pX) + pX) % pX; if ( vX == 0 ) {
vL = 0;
} else {
vL = 1; for ( ; 1 < vX; vX-- ) vL = sX[vL];
}
/**************************************************************************** ** *FOneFFE(<op>)...............oneofafinitefieldelement
*/ static Obj OneFFE(Obj op)
{
FF fX; // field of result
// get the field for the result
fX = FLD_FFE( op );
return NEW_FFE( fX, 1 );
}
/**************************************************************************** ** *FInvFFE(<op>)..............inverseoffinitefieldelement
*/ static Obj InvFFE(Obj op)
{
FFV v, vX; // value of operand, result
FF fX; // field of result const FFV* sX; // successor table of result field
// get the field for the result
fX = FLD_FFE( op );
sX = SUCC_FF( fX );
// get the operand
v = VAL_FFE( op ); if ( v == 0 ) return Fail;
static Obj QuoFFEFFE(Obj opL, Obj opR)
{
FFV vL, vR, vX; // value of left, right, result
FF fL, fR, fX; // field of left, right, result
UInt qL, qR, qX; // size of left, right, result
// get the values, handle trivial cases
vL = VAL_FFE( opL );
vR = VAL_FFE( opR );
// bring the two operands into a common field <fX>
fL = FLD_FFE( opL );
qL = SIZE_FF( fL );
fR = FLD_FFE( opR );
qR = SIZE_FF( fR );
if ( qL == qR ) {
fX = fL;
} elseif ( qL % qR == 0 && (qL-1) % (qR-1) == 0 ) {
fX = fL; if ( vR != 0 ) vR = (qL-1) / (qR-1) * (vR-1) + 1;
} elseif ( qR % qL == 0 && (qR-1) % (qL-1) == 0 ) {
fX = fR; if ( vL != 0 ) vL = (qR-1) / (qL-1) * (vL-1) + 1;
} else {
fX = CommonFF( fL, DegreeFFE(opL), fR, DegreeFFE(opR) ); if ( fX == 0 ) return CALL_2ARGS( QUO_FFE_LARGE, opL, opR );
qX = SIZE_FF( fX ); // if ( vL != 0 ) vL = (qX-1) / (qL-1) * (vL-1) + 1; if ( vL != 0 ) vL = ((qX-1) * (vL-1)) / (qL-1) + 1; // if ( vR != 0 ) vR = (qX-1) / (qR-1) * (vR-1) + 1; if ( vR != 0 ) vR = ((qX-1) * (vR-1)) / (qR-1) + 1;
}
if ( vR == 0 ) {
ErrorMayQuit("FFE operations: <divisor> must not be zero", 0, 0);
}
vX = QUO_FFV( vL, vR, SUCC_FF(fX) ); return NEW_FFE( fX, vX );
}
static Obj QuoFFEInt(Obj opL, Obj opR)
{
FFV vL, vR, vX; // value of left, right, result
FF fX; // field of result Int pX; // char. of result const FFV* sX; // successor table of result field
// get the field for the result
fX = FLD_FFE( opL );
pX = CHAR_FF( fX );
sX = SUCC_FF( fX );
// get the right operand
vX = ((INT_INTOBJ( opR ) % pX) + pX) % pX; if ( vX == 0 ) {
vR = 0;
} else {
vR = 1; for ( ; 1 < vX; vX-- ) vR = sX[vR];
}
// get the left operand
vL = VAL_FFE( opL );
if ( vR == 0 ) {
ErrorMayQuit("FFE operations: <divisor> must not be zero", 0, 0);
}
vX = QUO_FFV( vL, vR, sX ); return NEW_FFE( fX, vX );
}
static Obj QuoIntFFE(Obj opL, Obj opR)
{
FFV vL, vR, vX; // value of left, right, result
FF fX; // field of result Int pX; // char. of result const FFV* sX; // successor table of result field
// get the field for the result
fX = FLD_FFE( opR );
pX = CHAR_FF( fX );
sX = SUCC_FF( fX );
// get the left operand
vX = ((INT_INTOBJ( opL ) % pX) + pX) % pX; if ( vX == 0 ) {
vL = 0;
} else {
vL = 1; for ( ; 1 < vX; vX-- ) vL = sX[vL];
}
// get the right operand
vR = VAL_FFE( opR );
if ( vR == 0 ) {
ErrorMayQuit("FFE operations: <divisor> must not be zero", 0, 0);
}
vX = QUO_FFV( vL, vR, sX ); return NEW_FFE( fX, vX );
}
/**************************************************************************** ** *FPowFFEInt(<opL>,<opR>).........powerofafinitefieldelement ** **'PowFFEInt'returnsthepowerofthefinitefieldelement<opL>andthe **integer<opR>.Thepowerisrepresentedoverthefieldoverwhichthe **leftoperandisrepresented,evenifitliesinamuchsmallerfield. ** **'PowFFEInt'justdoestheconversionsmentionedaboveandthencallsthe **macro'POW_FFV'todotheactualexponentiation.
*/ static Obj PowFFEInt(Obj opL, Obj opR)
{
FFV vL, vX; // value of left, result Int vR; // value of right
FF fX; // field of result const FFV* sX; // successor table of result field
// get the field for the result
fX = FLD_FFE( opL );
sX = SUCC_FF( fX );
// get the right operand
vR = INT_INTOBJ( opR );
// get the left operand
vL = VAL_FFE( opL );
// if the exponent is negative, invert the left operand if ( vR < 0 ) { if ( vL == 0 ) {
ErrorMayQuit("FFE operations: <divisor> must not be zero", 0, 0);
}
vL = QUO_FFV( 1, vL, sX );
vR = -vR;
}
// catch the case when vL is zero. if( vL == 0 ) return NEW_FFE( fX, (vR == 0 ? 1 : 0 ) );
// reduce vR modulo the order of the multiplicative group first.
vR %= *sX;
/**************************************************************************** ** *FPowFFEFFE(<opL>,<opR>)......conjugateofafinitefieldelement
*/ static Obj PowFFEFFE(Obj opL, Obj opR)
{ // get the field for the result if ( CHAR_FF( FLD_FFE(opL) ) != CHAR_FF( FLD_FFE(opR) ) ) {
ErrorMayQuit("<x> and <y> have different characteristic", 0, 0);
}
static Obj FuncLOG_FFE_DEFAULT(Obj self, Obj opZ, Obj opR)
{
FFV vZ, vR; // value of left, right
FF fZ, fR, fX; // field of left, right, common
UInt qZ, qR, qX; // size of left, right, common Int a, b, c, d, t; // temporaries
if (!IS_FFE(opZ) || VAL_FFE(opZ) == 0) {
ErrorMayQuit("LogFFE: <z> must be a nonzero finite field element", 0, 0);
} if (!IS_FFE(opR) || VAL_FFE(opR) == 0) {
ErrorMayQuit("LogFFE: <r> must be a nonzero finite field element", 0, 0);
}
// get the values, handle trivial cases
vZ = VAL_FFE( opZ );
vR = VAL_FFE( opR );
// bring the two operands into a common field <fX>
fZ = FLD_FFE( opZ );
qZ = SIZE_FF( fZ );
fR = FLD_FFE( opR );
qR = SIZE_FF( fR );
// now solve <l> * (<vR>-1) = (<vZ>-1) % (<qX>-1)
a = 1; b = 0;
c = (Int) (vR-1); d = (Int) (qX-1); while ( d != 0 ) {
t = b; b = a - (c/d) * b; a = t;
t = d; d = c - (c/d) * d; c = t;
} if ( ((Int) (vZ-1)) % c != 0 ) { return Fail;
}
while (a < 0)
a+= (qX -1)/c;
// return the logarithm return INTOBJ_INT( (((UInt) (vZ-1) / c) * a) % ((UInt) (qX-1)) );
}
static Obj INT_FF(FF ff)
{
Obj conv; // conversion table, result Int q; // size of finite field Int p; // char of finite field const FFV * succ; // successor table of finite field
FFV z; // one element of finite field
UInt i; // loop variable
// if the conversion table is not already known, construct it #ifdef HPCGAP if ( NumFF < ff || (MEMBAR_READ(), ATOMIC_ELM_PLIST(IntFF, ff) == 0)) {
HashLock(&IntFF); #else if ( LEN_PLIST(IntFF) < ff || ELM_PLIST(IntFF,ff) == 0 ) { #endif
q = SIZE_FF( ff );
p = CHAR_FF( ff );
conv = NEW_PLIST_IMM( T_PLIST, p-1 );
succ = SUCC_FF( ff );
SET_LEN_PLIST( conv, p-1 );
z = 1; for ( i = 1; i < p; i++ ) {
SET_ELM_PLIST( conv, (z-1)/((q-1)/(p-1))+1, INTOBJ_INT(i) );
z = succ[ z ];
} #ifdef HPCGAP
GROW_PLIST(IntFF, ff);
ATOMIC_SET_ELM_PLIST( IntFF, ff, conv );
MEMBAR_WRITE();
NumFF = LEN_PLIST(IntFF);
HashUnlock(&IntFF); #else
AssPlist( IntFF, ff, conv ); #endif
}
static Obj FuncINT_FFE_DEFAULT(Obj self, Obj z)
{
FFV v; // value of finite field element
FF ff; // finite field Int q; // size of finite field Int p; // char of finite field
Obj conv; // conversion table
// get the value
v = VAL_FFE( z );
// special case for 0 if ( v == 0 ) { return INTOBJ_INT( 0 );
}
// get the field, size, characteristic, and conversion table
ff = FLD_FFE( z );
q = SIZE_FF( ff );
p = CHAR_FF( ff );
conv = INT_FF( ff );
// check the argument if ( (v-1) % ((q-1)/(p-1)) != 0 ) {
ErrorMayQuit("IntFFE: <z> must lie in prime field", 0, 0);
}
// convert the value into the prime field
v = (v-1) / ((q-1)/(p-1)) + 1;
// return the integer value return ELM_PLIST( conv, v );
}
// expose MAXSIZE_GF_INTERNAL from ffdata.h to the GAP library
ExportAsConstantGVar(MAXSIZE_GF_INTERNAL);
return0;
}
/**************************************************************************** ** *FInitInfoFinfield()...............tableofinitfunctions
*/ static StructInitInfo module = { // init struct using C99 designated initializers; for a full list of // fields, please refer to the definition of StructInitInfo
.type = MODULE_BUILTIN,
.name = "finfield",
.initKernel = InitKernel,
.initLibrary = InitLibrary,
};
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.55Bemerkung:
(vorverarbeitet am 2026-09-28)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.