staticvoid MakeFieldInfo8Bit(UInt q)
{
FF gfq; // the field
UInt p; // characteristic
UInt d; // degree
UInt i, j, k, l; // loop variables
UInt e; // number of elements per byte
UInt pows[7]; // table of powers of q for packing and unpacking bytes
Obj info; // The table being constructed
FFV mult; // multiplier for scalar product
FFV prod; // used in scalar product
UInt val; // used to build up some answers
UInt val0;
UInt elt, el1, el2; // used to build up some answers const FFV * succ;
p = (UInt)PbyQ[q];
d = (UInt)DbyQ[q];
gfq = FiniteField(p, d);
e = 0; for (i = 1; i <= 256; i *= q)
pows[e++] = i;
pows[e] = i; // simplifies things to have one more
e--;
GAP_ASSERT(e <= 5);
info = NewWordSizedBag(T_DATOBJ, sizeof(struct FieldInfo8Bit));
SetTypeDatObj(info, TYPE_FIELDINFO_8BIT);
succ = SUCC_FF(gfq);
// from here to the end, no garbage collections should happen
FieldInfo8BitPtr fi = FIELDINFO_8BIT(info);
fi->q = q;
fi->p = p;
fi->d = d;
fi->e = e;
// conversion tables FFV to/from our numbering // we assume that 0 and 1 are always the zero and one // of the field. In char 2, we assume that xor corresponds // to addition, otherwise, the order doesn't matter
UInt1 * convtab = fi->FELT_FFE; if (p != 2) for (i = 0; i < q; i++)
convtab[i] = (UInt1)i; else for (i = 0; i < q; i++)
convtab[i] = Char2Lookup[d][i];
// simply invert the permutation to get the other one for (i = 0; i < q; i++) {
j = convtab[i];
fi->FFE_FELT[j] = NEW_FFE(gfq, i);
}
// Now we need to store the position in Elements(GF(q)) of each field // element for the sake of NumberFFVector // // The rules for < between finite field elements make this a bit // complex for non-prime fields
// deal with zero and one
fi->GAPSEQ[0] = INTOBJ_INT(0);
fi->GAPSEQ[fi->FELT_FFE[1]] = INTOBJ_INT(1);
if (q != 2) { if (d == 1) for (i = 2; i < q; i++)
fi->GAPSEQ[i] = INTOBJ_INT(i); else { // run through subfields, filling in entry for all the new // elements of each field in turn
UInt q1 = 1;
UInt pos = 2; for (i = 1; i <= d; i++) {
q1 *= p; if (d % i == 0) { for (j = 2; j < q1; j++) {
UInt place =
fi->FELT_FFE[1 + (j - 1) * (q - 1) / (q1 - 1)]; if (fi->GAPSEQ[place] == 0) {
fi->GAPSEQ[place] = INTOBJ_INT(pos);
pos++;
}
}
}
}
}
}
// entry setting table SETELT...[(i*e+j)*256 +k] is the result // of overwriting the jth element with i in the byte k for (i = 0; i < q; i++) for (j = 0; j < e; j++) { Int iej_cache = (i * e + j) * 256; for (k = 0; k < 256; k++)
fi->SETELT[iej_cache + k] =
(UInt1)((k / pows[j + 1]) * pows[j + 1] + i * pows[j] +
(k % pows[j]));
}
// entry access GETELT...[i*256+j] recovers the ith entry from the // byte j for (i = 0; i < e; i++) for (j = 0; j < 256; j++)
fi->GETELT[i * 256 + j] = (UInt1)(j / pows[i]) % q;
// scalar * vector multiply SCALAR...[i*256+j] is the scalar // product of the byte j with the felt i for (i = 0; i < q; i++) {
mult = VAL_FFE(FFE_FELT_FIELDINFO_8BIT(info, i)); for (j = 0; j < 256; j++) {
val = 0; for (k = 0; k < e; k++) {
elt = VAL_FFE(
FFE_FELT_FIELDINFO_8BIT(info, fi->GETELT[k * 256 + j]));
prod = PROD_FFV(elt, mult, succ);
val += pows[k] * FELT_FFE_FIELDINFO_8BIT(info)[prod];
}
fi->SCALAR[i * 256 + j] = val;
}
}
// inner product INNER...[i+256*j] is a byte whose LS entry is the // contribution to the inner product of bytes i and j for (i = 0; i < 256; i++) for (j = i; j < 256; j++) {
val = 0; for (k = 0; k < e; k++) {
el1 = VAL_FFE(
FFE_FELT_FIELDINFO_8BIT(info, fi->GETELT[k * 256 + i]));
el2 = VAL_FFE(
FFE_FELT_FIELDINFO_8BIT(info, fi->GETELT[k * 256 + j]));
elt = PROD_FFV(el1, el2, succ);
val = SUM_FFV(val, elt, succ);
}
val = fi->SETELT[256 * e * FELT_FFE_FIELDINFO_8BIT(info)[val]];
fi->INNER[i + 256 * j] = val;
fi->INNER[j + 256 * i] = val;
}
// PMULL and PMULU are the lower and upper bytes of the product // of single-byte polynomials for (i = 0; i < 256; i++) for (j = i; j < 256; j++) {
val0 = 0; for (k = 0; k < e; k++) {
val = 0; for (l = 0; l <= k; l++) {
el1 = VAL_FFE(FFE_FELT_FIELDINFO_8BIT(
info, fi->GETELT[l * 256 + i]));
el2 = VAL_FFE(FFE_FELT_FIELDINFO_8BIT(
info, fi->GETELT[(k - l) * 256 + j]));
elt = PROD_FFV(el1, el2, succ);
val = SUM_FFV(val, elt, succ);
}
val0 += pows[k] * FELT_FFE_FIELDINFO_8BIT(info)[val];
}
fi->PMULL[i + 256 * j] = val0;
fi->PMULL[j + 256 * i] = val0;
// if there is just one entry per byte then we don't need the // upper half if (ELS_BYTE_FIELDINFO_8BIT(info) > 1) {
val0 = 0; for (k = e; k < 2 * e - 1; k++) {
val = 0; for (l = k - e + 1; l < e; l++) {
el1 = VAL_FFE(FFE_FELT_FIELDINFO_8BIT(
info, fi->GETELT[l * 256 + i]));
el2 = VAL_FFE(FFE_FELT_FIELDINFO_8BIT(
info, fi->GETELT[(k - l) * 256 + j]));
elt = PROD_FFV(el1, el2, succ);
val = SUM_FFV(val, elt, succ);
}
val0 += pows[k - e] * FELT_FFE_FIELDINFO_8BIT(info)[val];
}
fi->PMULU[i + 256 * j] = val0;
fi->PMULU[j + 256 * i] = val0;
}
}
// In odd characteristic, we need the addition table // ADD...[i*256+j] is the vector sum of bytes i and j if (p != 2) { for (i = 0; i < 256; i++) for (j = i; j < 256; j++) {
val = 0; for (k = 0; k < e; k++) {
el1 = VAL_FFE(FFE_FELT_FIELDINFO_8BIT(
info, fi->GETELT[k * 256 + i]));
el2 = VAL_FFE(FFE_FELT_FIELDINFO_8BIT(
info, fi->GETELT[k * 256 + j]));
val += pows[k] * FELT_FFE_FIELDINFO_8BIT(
info)[SUM_FFV(el1, el2, succ)];
}
fi->ADD[i + 256 * j] = val;
fi->ADD[j + 256 * i] = val;
}
}
#ifdef HPCGAP
MakeBagReadOnly(info); #endif // remember the result #ifdef HPCGAP
ATOMIC_SET_ELM_PLIST_ONCE(FieldInfo8Bit, q, info); #else
SET_ELM_PLIST(FieldInfo8Bit, q, info); #endif
CHANGED_BAG(FieldInfo8Bit);
}
Obj GetFieldInfo8Bit(UInt q)
{
Obj info;
GAP_ASSERT(2 < q && q <= 256); #ifdef HPCGAP
info = ATOMIC_ELM_PLIST(FieldInfo8Bit, q); if (info == 0) {
MakeFieldInfo8Bit(q);
info = ATOMIC_ELM_PLIST(FieldInfo8Bit, q);
} #else
info = ELM_PLIST(FieldInfo8Bit, q); if (info == 0) {
MakeFieldInfo8Bit(q);
info = ELM_PLIST(FieldInfo8Bit, q);
} #endif return info;
}
if (q < q1) {
ErrorMayQuit("Cannot convert a vector compressed over GF(%d) to " "small field GF(%d)",
q1, q);
}
if (((q - 1) % (q1 - 1)) != 0) {
ErrorMayQuit( "Cannot convert a vector compressed over GF(%d) to GF(%d)", q1,
q);
}
if (DoFilter(IsLockedRepresentationVector, vec) == True) {
ErrorMayQuit("Cannot convert a locked vector compressed over " "GF(%d) to GF(%d)",
q1, q);
}
// extract the required info
len = LEN_VEC8BIT(vec);
info = GetFieldInfo8Bit(q);
info1 = GetFieldInfo8Bit(q1);
GAP_ASSERT(P_FIELDINFO_8BIT(info) == P_FIELDINFO_8BIT(info1));
GAP_ASSERT(!(D_FIELDINFO_8BIT(info) % D_FIELDINFO_8BIT(info1)));
els = ELS_BYTE_FIELDINFO_8BIT(info);
els1 = ELS_BYTE_FIELDINFO_8BIT(info1);
if (len == 0) {
SET_FIELD_VEC8BIT(vec, q); return;
}
// enlarge the bag
ResizeWordSizedBag(vec, SIZE_VEC8BIT(len, els));
staticvoid ConvVec8Bit(Obj list, UInt q)
{ Int len; // logical length of the vector Int i; // loop variable
UInt p; // char
UInt d; // degree
FF f; // field
Obj info; // field info object
UInt elts; // elements per byte const UInt1 * settab; // element setting table const UInt1 * convtab; // FFE -> FELT conversion table
Obj firstthree[3]; // the first three entries may get clobbered my the // early bytes
UInt e; // loop variable
UInt1 byte; // byte under construction
UInt1 * ptr; // place to put byte
Obj elt;
UInt val;
UInt nsize;
Obj type;
if (q > 256)
ErrorQuit("Field size %d is too much for 8 bits", q, 0); if (q == 2)
ErrorQuit("GF2 has its own representation", 0, 0);
// already in the correct representation if (IS_VEC8BIT_REP(list)) {
UInt q1 = FIELD_VEC8BIT(list); if (q1 == q) return; elseif (q1 < q && ((q - 1) % (q1 - 1)) == 0) {
RewriteVec8Bit(list, q); return;
} // remaining case is list is written over too large a field // pass through to the generic code
} elseif (IS_GF2VEC_REP(list)) {
RewriteGF2Vec(list, q); return;
}
len = LEN_LIST(list);
// OK, so now we know which field we want, set up data
info = GetFieldInfo8Bit(q);
p = P_FIELDINFO_8BIT(info);
d = D_FIELDINFO_8BIT(info);
f = FiniteField(p, d);
elts = ELS_BYTE_FIELDINFO_8BIT(info);
// We may need to resize first, as small lists get BIGGER // in this process
nsize = SIZE_VEC8BIT(len, elts); if (nsize > SIZE_OBJ(list))
ResizeWordSizedBag(list, nsize);
// writing the first byte may clobber the third list entry // before we have read it, so we take a copy
firstthree[0] = ELM0_LIST(list, 1);
firstthree[1] = ELM0_LIST(list, 2);
firstthree[2] = ELM0_LIST(list, 3);
// main loop -- e is the element within byte
e = 0;
byte = 0;
ptr = BYTES_VEC8BIT(list); for (i = 1; i <= len; i++) {
elt = (i <= 3) ? firstthree[i - 1] : ELM_LIST(list, i);
GAP_ASSERT(CHAR_FF(FLD_FFE(elt)) == p);
GAP_ASSERT(d % DegreeFFE(elt) == 0);
val = VAL_FFE(elt); if (val != 0 && FLD_FFE(elt) != f) {
val = 1 + (val - 1) * (q - 1) / (SIZE_FF(FLD_FFE(elt)) - 1);
} // Must get these afresh after every list access, just in case this is // a virtual list whose accesses might cause a garbage collection
settab = SETELT_FIELDINFO_8BIT(info);
convtab = FELT_FFE_FIELDINFO_8BIT(info);
byte = settab[(e + elts * convtab[val]) * 256 + byte]; if (++e == elts || i == len) {
*ptr++ = byte;
byte = 0;
e = 0;
}
}
// it can happen that the few bytes after the end of the data are // not zero, because they had data in them in the old version of the list // In most cases this doesn't matter, but in characteristic 2, we must // clear up to the end of the word, so that AddCoeffs behaves correctly. // // SL -- lets do this in all characteristics, it can never hurt
while ((ptr - BYTES_VEC8BIT(list)) % sizeof(UInt))
*ptr++ = 0;
// retype and resize bag if (nsize != SIZE_OBJ(list))
ResizeWordSizedBag(list, nsize);
SET_LEN_VEC8BIT(list, len);
SET_FIELD_VEC8BIT(list, q);
type = TypeVec8Bit(q, IS_MUTABLE_OBJ(list));
SetTypeDatObj(list, type);
RetypeBag(list, T_DATOBJ);
}
static UInt LcmDegree(UInt d, UInt d1)
{
UInt x, y, g;
x = d;
y = d1; while (x != 0 && y != 0) { if (x <= y)
y = y % x; else
x = x % y;
} if (x == 0)
g = y; else
g = x; return (d * d1) / g;
}
static Obj NewVec8Bit(Obj list, UInt q)
{ Int len; // logical length of the vector Int i; // loop variable
UInt p; // char
UInt d; // degree
FF f; // field
Obj info; // field info object
UInt elts; // elements per byte const UInt1 * settab; // element setting table const UInt1 * convtab; // FFE -> FELT conversion table
UInt e; // loop variable
UInt1 byte; // byte under construction
UInt1 * ptr; // place to put byte
Obj elt;
UInt val;
UInt nsize;
Obj type;
Obj res; // resulting 8bit vector object
if (q > 256)
ErrorQuit("Field size %d is too much for 8 bits", q, 0); if (q == 2)
ErrorQuit("GF2 has its own representation", 0, 0);
// already in the correct representation if (IS_VEC8BIT_REP(list)) {
UInt q1 = FIELD_VEC8BIT(list); if (q1 == q) {
res = CopyVec8Bit(list, 1); if (!IS_MUTABLE_OBJ(list)) // index 0 is for immutable vectors
SetTypeDatObj(res, TypeVec8Bit(q, 0)); return res;
} elseif (q1 < q && ((q - 1) % (q1 - 1)) == 0) { // rewriting to a larger field
res = CopyVec8Bit(list, 1);
RewriteVec8Bit(res, q); // TODO: rework RewriteVec8Bit and avoid calling CopyVec8Bit if (!IS_MUTABLE_OBJ(list))
SetTypeDatObj(res, TypeVec8Bit(q, 0)); return res;
} // remaining case is list is written over too large a field // pass through to the generic code
} elseif (IS_GF2VEC_REP(list)) {
res = ShallowCopyVecGF2(list);
RewriteGF2Vec(res, q); // TODO: rework RewriteGF2Vec and avoid calling ShallowCopyVecGF2 if (!IS_MUTABLE_OBJ(list))
SetTypeDatObj(res, TypeVec8Bit(q, 0)); return res;
}
// OK, so now we know which field we want, set up data
info = GetFieldInfo8Bit(q);
p = P_FIELDINFO_8BIT(info);
d = D_FIELDINFO_8BIT(info);
f = FiniteField(p, d);
// determine the size and create a new bag
len = LEN_LIST(list);
elts = ELS_BYTE_FIELDINFO_8BIT(info);
nsize = SIZE_VEC8BIT(len, elts);
res = NewWordSizedBag(T_DATOBJ, nsize);
// main loop -- e is the element within byte
e = 0;
byte = 0;
ptr = BYTES_VEC8BIT(res); for (i = 1; i <= len; i++) {
elt = ELM_LIST(list, i);
GAP_ASSERT(CHAR_FF(FLD_FFE(elt)) == p);
GAP_ASSERT(d % DegreeFFE(elt) == 0);
val = VAL_FFE(elt); if (val != 0 && FLD_FFE(elt) != f) {
val = 1 + (val - 1) * (q - 1) / (SIZE_FF(FLD_FFE(elt)) - 1);
} // Must get these afresh after every list access, just in case this is // a virtual list whose accesses might cause a garbage collection
settab = SETELT_FIELDINFO_8BIT(info);
convtab = FELT_FFE_FIELDINFO_8BIT(info);
byte = settab[(e + elts * convtab[val]) * 256 + byte]; if (++e == elts || i == len) {
*ptr++ = byte;
byte = 0;
e = 0;
}
}
// retype bag
SET_LEN_VEC8BIT(res, len);
SET_FIELD_VEC8BIT(res, q);
type = TypeVec8Bit(q, IS_MUTABLE_OBJ(list));
SetTypeDatObj(res, type);
// resize the list and retype it, in this order if (True == DoFilter(IsLockedRepresentationVector, list)) {
ErrorMayQuit( "Attempt to convert locked compressed vector to plain list", 0, 0);
}
len = LEN_VEC8BIT(list);
q = FIELD_VEC8BIT(list);
info = GetFieldInfo8Bit(q);
elts = ELS_BYTE_FIELDINFO_8BIT(info);
if (len != 0) {
gettab = GETELT_FIELDINFO_8BIT(info); // keep the first two entries // because setting the third destroys them
first = FFE_FELT_FIELDINFO_8BIT(info,
gettab[CONST_BYTES_VEC8BIT(list)[0]]); if (len > 1)
second = FFE_FELT_FIELDINFO_8BIT(
info, gettab[256 * (1 % elts) +
CONST_BYTES_VEC8BIT(list)[1 / elts]]);
// replace the bits by FF elts as the case may be // this must of course be done from the end of the list backwards for (i = len; 2 < i; i--) {
fieldobj = FFE_FELT_FIELDINFO_8BIT(
info, gettab[256 * ((i - 1) % elts) +
CONST_BYTES_VEC8BIT(list)[(i - 1) / elts]]);
SET_ELM_PLIST(list, i, fieldobj);
} if (len > 1)
SET_ELM_PLIST(list, 2, second);
SET_ELM_PLIST(list, 1, first);
} // Null out any entries after the end of valid data // As the size of the VEC8BIT might not evenly divide sizeof(Int), we // cannot use PLIST methods to set the end of the list to zero
startblank = (Char *)(PTR_BAG(list) + (len + 1));
endblank = (Char *)PTR_BAG(list) + SIZE_BAG(list);
memset(startblank, 0, endblank - startblank);
CHANGED_BAG(list);
}
/**************************************************************************** ** *FFuncPLAIN_VEC8BIT(<self>,<list>)....convertbackintoplainlist
*/ static Obj FuncPLAIN_VEC8BIT(Obj self, Obj list)
{ if (!IS_VEC8BIT_REP(list)) {
RequireArgument(SELF_NAME, list, "must be an 8bit vector");
} if (DoFilter(IsLockedRepresentationVector, list) == True) {
ErrorMayQuit("Cannot convert a locked vector compressed over " "GF(%d) to a plain list",
FIELD_VEC8BIT(list), 0);
}
PlainVec8Bit(list);
static Obj FuncADD_ROWVECTOR_VEC8BITS_5(
Obj self, Obj vl, Obj vr, Obj mul, Obj from, Obj to)
{
UInt q;
UInt len;
len = LEN_VEC8BIT(vl); // There may be nothing to do if (LT(to, from)) return (Obj)0;
if (len != LEN_VEC8BIT(vr)) {
ErrorMayQuit("AddRowVector: <left> and <right> must be " "vectors of the same length", 0, 0);
} if (LT(INTOBJ_INT(len), to)) {
ErrorMayQuit("AddRowVector: <to> (%d) is greater than the " "length of the vectors (%d)",
INT_INTOBJ(to), len);
} if (LT(to, from)) return (Obj)0;
// Now we know that the characteristics must match, but not the fields
q = FIELD_VEC8BIT(vl);
// fix up fields if necessary if (q != FIELD_VEC8BIT(vr) || q != SIZE_FF(FLD_FFE(mul))) {
Obj info, info1;
UInt d, d1, q1, d2, d0, q0, p, i;
FFV val;
// find a common field
info = GetFieldInfo8Bit(q);
d = D_FIELDINFO_8BIT(info);
q1 = FIELD_VEC8BIT(vr);
info1 = GetFieldInfo8Bit(q1);
d1 = D_FIELDINFO_8BIT(info1);
d2 = DegreeFFE(mul);
d0 = LcmDegree(d, d1);
d0 = LcmDegree(d0, d2);
p = P_FIELDINFO_8BIT(info);
GAP_ASSERT(p == P_FIELDINFO_8BIT(info1));
GAP_ASSERT(p == CHAR_FF(FLD_FFE(mul)));
q0 = 1; for (i = 0; i < d0; i++)
q0 *= p;
// if the exponent is bigger than 31, overflow changes the value to 0 if (d0 > 8 || q0 > 256) return TRY_NEXT_METHOD; if ((q0 > q && DoFilter(IsLockedRepresentationVector, vl) == True) ||
(q0 > q1 && DoFilter(IsLockedRepresentationVector, vr) == True)) return TRY_NEXT_METHOD;
RewriteVec8Bit(vl, q0);
RewriteVec8Bit(vr, q0);
val = VAL_FFE(mul); if (val != 0)
val = 1 + (val - 1) * (q0 - 1) / (SIZE_FF(FLD_FFE(mul)) - 1);
mul = NEW_FFE(FiniteField(p, d0), val);
}
static Obj FuncADD_ROWVECTOR_VEC8BITS_3(Obj self, Obj vl, Obj vr, Obj mul)
{
UInt q; if (LEN_VEC8BIT(vl) != LEN_VEC8BIT(vr)) {
ErrorMayQuit( "SUM: <left> and <right> must be vectors of the same length", 0, 0);
} // Now we know that the characteristics must match, but not the fields
q = FIELD_VEC8BIT(vl);
// fix up fields if necessary if (q != FIELD_VEC8BIT(vr) || q != SIZE_FF(FLD_FFE(mul))) {
Obj info, info1;
UInt d, d1, q1, d2, d0, q0, p, i;
FFV val; // find a common field
info = GetFieldInfo8Bit(q);
d = D_FIELDINFO_8BIT(info);
q1 = FIELD_VEC8BIT(vr);
info1 = GetFieldInfo8Bit(q1);
d1 = D_FIELDINFO_8BIT(info1);
d2 = DegreeFFE(mul);
d0 = LcmDegree(d, d1);
d0 = LcmDegree(d0, d2);
p = P_FIELDINFO_8BIT(info);
GAP_ASSERT(p == P_FIELDINFO_8BIT(info1));
GAP_ASSERT(p == CHAR_FF(FLD_FFE(mul)));
q0 = 1; for (i = 0; i < d0; i++)
q0 *= p;
// if the exponent is bigger than 31, overflow changes the value to 0 if (d0 > 8 || q0 > 256) return TRY_NEXT_METHOD; if ((q0 > q &&
CALL_1ARGS(IsLockedRepresentationVector, vl) == True) ||
(q0 > q1 && CALL_1ARGS(IsLockedRepresentationVector, vr) == True)) return TRY_NEXT_METHOD;
RewriteVec8Bit(vl, q0);
RewriteVec8Bit(vr, q0);
val = VAL_FFE(mul); if (val != 0)
val = 1 + (val - 1) * (q0 - 1) / (SIZE_FF(FLD_FFE(mul)) - 1);
mul = NEW_FFE(FiniteField(p, d0), val);
}
AddVec8BitVec8BitMultInner(vl, vl, vr, mul, 1, LEN_VEC8BIT(vl)); return (Obj)0;
}
static Obj FuncADD_ROWVECTOR_VEC8BITS_2(Obj self, Obj vl, Obj vr)
{
UInt q; if (LEN_VEC8BIT(vl) != LEN_VEC8BIT(vr)) {
ErrorMayQuit( "SUM: <left> and <right> must be vectors of the same length", 0, 0);
} // Now we know that the characteristics must match, but not the fields
q = FIELD_VEC8BIT(vl); // fix up fields if necessary if (q != FIELD_VEC8BIT(vr)) {
Obj info1;
Obj info;
UInt d, d1, q1, d0, q0, p, i; // find a common field
info = GetFieldInfo8Bit(q);
d = D_FIELDINFO_8BIT(info);
q1 = FIELD_VEC8BIT(vr);
info1 = GetFieldInfo8Bit(q1);
d1 = D_FIELDINFO_8BIT(info1);
d0 = LcmDegree(d, d1);
p = P_FIELDINFO_8BIT(info);
GAP_ASSERT(p == P_FIELDINFO_8BIT(info1));
q0 = 1; for (i = 0; i < d0; i++)
q0 *= p;
// if the exponent is bigger than 31, overflow changes the value to 0 if (d0 > 8 || q0 > 256) return TRY_NEXT_METHOD; if ((q0 > q &&
CALL_1ARGS(IsLockedRepresentationVector, vl) == True) ||
(q0 > q1 && CALL_1ARGS(IsLockedRepresentationVector, vr) == True)) return TRY_NEXT_METHOD;
RewriteVec8Bit(vl, q0);
RewriteVec8Bit(vr, q0);
q = q0;
}
AddVec8BitVec8BitInner(vl, vl, vr, 1, LEN_VEC8BIT(vl)); return (Obj)0;
}
// we stop a little short, so as to handle the final byte separately
endL = ptrL + lenl / elts;
endR = ptrR + lenr / elts;
gettab = GETELT_FIELDINFO_8BIT(info);
ffe_elt = CONST_FFE_FELT_FIELDINFO_8BIT(info); while (ptrL < endL && ptrR < endR) { if (*ptrL == *ptrR) {
ptrL++;
ptrR++;
} else { for (e = 0; e < elts; e++) {
vall = gettab[*ptrL + 256 * e];
valr = gettab[*ptrR + 256 * e]; if (vall != valr) { if (LT(ffe_elt[vall], ffe_elt[valr])) return -1; else return1;
}
}
ErrorQuit("panic: bytes differed but all entries the same", 0, 0);
}
} // now the final byte if (lenl < lenr)
len = lenl; else
len = lenr;
// look first at the shared part for (e = 0; e < (len % elts); e++) {
vall = gettab[*ptrL + 256 * e];
valr = gettab[*ptrR + 256 * e]; if (vall != valr) { if (LT(ffe_elt[vall], ffe_elt[valr])) return -1; else return1;
}
} // if that didn't decide then the longer list is bigger if (lenr > lenl) return -1; elseif (lenr == lenl) return0; else return1;
}
/**************************************************************************** ** *FDistDistrib8Bits(<veclis>,<ovec>,<d>,<osum>,<pos>,<l>,<m>) **
*/ staticvoid DistDistrib8Bits(
Obj veclis, // pointers to matrix vectors and their multiples
Obj vec, // vector we compute distance to
Obj d, // distances list
Obj sum, // position of the sum vector
UInt pos, // recursion depth
UInt l // length of basis
)
{
UInt i;
UInt di;
Obj cnt;
Obj vp;
Obj one;
Obj tmp;
UInt len;
UInt q;
vp = ELM_PLIST(veclis, pos);
one = INTOBJ_INT(1);
len = LEN_VEC8BIT(sum);
q = FIELD_VEC8BIT(sum); for (i = 0; i < q; i++) { if (pos < l) {
DistDistrib8Bits(veclis, vec, d, sum, pos + 1, l);
} else {
di = DistanceVec8Bits(sum, vec);
cnt = ELM_PLIST(d, di + 1); if (IS_INTOBJ(cnt) && SUM_INTOBJS(tmp, cnt, one)) {
cnt = tmp;
SET_ELM_PLIST(d, di + 1, cnt);
} else {
cnt = SumInt(cnt, one);
SET_ELM_PLIST(d, di + 1, cnt);
CHANGED_BAG(d);
}
}
AddVec8BitVec8BitInner(sum, sum, ELM_PLIST(vp, i + 1), 1, len);
}
TakeInterrupt();
}
static Obj FuncDISTANCE_DISTRIB_VEC8BITS(
Obj self,
Obj veclis, // pointers to matrix vectors and their multiples
Obj vec, // vector we compute distance to
Obj d) // distances list
{
Obj sum; // sum vector
UInt len;
UInt q;
len = LEN_VEC8BIT(vec);
q = FIELD_VEC8BIT(vec);
// get space for sum vector and zero out
sum = ZeroVec8Bit(q, len, 0); // do the recursive work
DistDistrib8Bits(veclis, vec, d, sum, 1, LEN_PLIST(veclis));
static UInt
AClosVec8Bit(Obj veclis, // pointers to matrix vectors and their multiples
Obj vec, // vector we compute distance to
Obj sum, // position of the sum vector
UInt pos, // recursion depth
UInt l, // length of basis
UInt cnt, // number of vectors used already
UInt stop, // stop value
UInt bd, // best distance so far
Obj bv, // best vector so far
Obj coords,
Obj bcoords)
{
UInt i, j;
UInt di;
Obj vp;
UInt q;
UInt len;
// This is the case where we do not add any multiple of // the current basis vector if (pos + cnt < l) {
bd = AClosVec8Bit(veclis, vec, sum, pos + 1, l, cnt, stop, bd, bv,
coords, bcoords); if (bd <= stop) { return bd;
}
}
q = FIELD_VEC8BIT(vec);
len = LEN_VEC8BIT(vec);
vp = ELM_PLIST(veclis, pos);
// we need to add each scalar multiple and recurse for (i = 1; i < q; i++) {
AddVec8BitVec8BitInner(sum, sum, ELM_PLIST(vp, i), 1, len); if (coords)
SET_ELM_PLIST(coords, pos, INTOBJ_INT(i)); if (cnt == 0) { // do we have a new best case
di = DistanceVec8Bits(sum, vec); if (di < bd) {
bd = di;
OverwriteVec8Bit(bv, sum); if (coords) for (j = 1; j <= l; j++) {
Obj x;
x = ELM_PLIST(coords, j);
SET_ELM_PLIST(bcoords, j, x);
} if (bd <= stop) return bd;
}
} elseif (pos < l) {
bd = AClosVec8Bit(veclis, vec, sum, pos + 1, l, cnt - 1, stop, bd,
bv, coords, bcoords); if (bd <= stop) { return bd;
}
}
} // reset component
AddVec8BitVec8BitInner(sum, sum, ELM_PLIST(vp, q), 1, len); if (coords)
SET_ELM_PLIST(coords, pos, INTOBJ_INT(0));
sum = ZeroVec8Bit(q, len, 1);
best = ZeroVec8Bit(q, len, 1);
// do the recursive work
AClosVec8Bit(veclis, vec, sum, 1, LEN_PLIST(veclis), INT_INTOBJ(cnt),
INT_INTOBJ(stop), len + 1, // maximal value +1
best, (Obj)0, (Obj)0);
sum = ZeroVec8Bit(q, len, 1);
best = ZeroVec8Bit(q, len, 1);
len2 = LEN_PLIST(veclis);
coords = NEW_PLIST(T_PLIST_CYC, len2);
bcoords = NEW_PLIST(T_PLIST_CYC, len2);
SET_LEN_PLIST(coords, len2);
SET_LEN_PLIST(bcoords, len2); for (i = 1; i <= len2; i++) {
SET_ELM_PLIST(coords, i, INTOBJ_INT(0));
SET_ELM_PLIST(bcoords, i, INTOBJ_INT(0));
}
// do the recursive work
AClosVec8Bit(veclis, vec, sum, 1, LEN_PLIST(veclis), INT_INTOBJ(cnt),
INT_INTOBJ(stop), len + 1, // maximal value +1
best, coords, bcoords);
info = GetFieldInfo8Bit(FIELD_VEC8BIT(vec));
elts = ELS_BYTE_FIELDINFO_8BIT(info);
gettab = GETELT_FIELDINFO_8BIT(info);
convtab = GAPSEQ_FELT_FIELDINFO_8BIT(info);
ptrS = CONST_BYTES_VEC8BIT(vec);
len = LEN_VEC8BIT(vec);
res = INTOBJ_INT(0);
f = INTOBJ_INT(FIELD_VEC8BIT(vec)); // Field size as GAP integer
if (len == 0) return INTOBJ_INT(1);
for (i = 0; i < len; i++) {
elt = convtab[gettab[ptrS[i / elts] + 256 * (i % elts)]];
res = ProdInt(res, f); // ``shift''
res = SumInt(res, elt); if (!IS_INTOBJ(res)) { // a garbage collection might have moved the pointers
gettab = GETELT_FIELDINFO_8BIT(info);
convtab = GAPSEQ_FELT_FIELDINFO_8BIT(info);
ptrS = CONST_BYTES_VEC8BIT(vec);
}
}
// check that <list> is mutable
RequireMutable("List Assignment", list, "list");
// get the position
p = GetPositiveSmallInt("ASS_VEC8BIT", pos);
info = GetFieldInfo8Bit(FIELD_VEC8BIT(list));
elts = ELS_BYTE_FIELDINFO_8BIT(info);
chr = P_FIELDINFO_8BIT(info);
d = D_FIELDINFO_8BIT(info);
q = Q_FIELDINFO_8BIT(info);
if (p <= LEN_VEC8BIT(list) + 1) { if (LEN_VEC8BIT(list) + 1 == p) { if (True == DoFilter(IsLockedRepresentationVector, list)) {
ErrorReturnVoid("List assignment would increase length of " "locked compressed vector", 0, 0, "You can `return;' to ignore the assignment"); return;
}
ResizeWordSizedBag(list, SIZE_VEC8BIT(p, elts));
SET_LEN_VEC8BIT(list, p); // Pr("Extending 8 bit vector by 1",0,0);
} if (!IS_FFE(elm)) {
newelm = DoAttribute(AsInternalFFE, elm); if (newelm != Fail)
elm = newelm;
} if (IS_FFE(elm) && chr == CharFFE(elm)) {
// We may need to rewrite the vector over a larger field if (d % DegreeFFE(elm) != 0) { // Pr("Rewriting over larger field",0,0);
f = CommonFF(FiniteField(chr, d), d, FLD_FFE(elm),
DegreeFFE(elm)); if (f && SIZE_FF(f) <= 256) {
RewriteVec8Bit(list, SIZE_FF(f));
info = GetFieldInfo8Bit(FIELD_VEC8BIT(list));
elts = ELS_BYTE_FIELDINFO_8BIT(info);
chr = P_FIELDINFO_8BIT(info);
d = D_FIELDINFO_8BIT(info);
q = Q_FIELDINFO_8BIT(info);
} else {
PlainVec8Bit(list);
AssPlistFfe(list, p, elm); return;
}
}
v = VAL_FFE(elm);
// may need to promote the element to a bigger field // or restrict it to a smaller one if (v != 0 && q != SIZE_FF(FLD_FFE(elm))) {
GAP_ASSERT(
((v - 1) * (q - 1)) % (SIZE_FF(FLD_FFE(elm)) - 1) == 0);
v = 1 + (v - 1) * (q - 1) / (SIZE_FF(FLD_FFE(elm)) - 1);
}
// We fall through here if the assignment position is so large // as to leave a hole, or if the object to be assigned is // not of the right characteristic, or would create too large a field
// check that <list> is mutable
RequireMutable("List Unbind", list, "list"); if (True == DoFilter(IsLockedRepresentationVector, list)) {
ErrorReturnVoid( "Unbind of entry of locked compressed vector is forbidden", 0, 0, "You can `return;' to ignore the assignment"); return0;
}
// get the position
p = GetPositiveSmallInt(SELF_NAME, pos);
// if we unbind the last position keep the representation if (LEN_VEC8BIT(list) < p) {
;
} elseif (LEN_VEC8BIT(list) == p) { // zero out the last entry first, for safety
info = GetFieldInfo8Bit(FIELD_VEC8BIT(list));
elts = ELS_BYTE_FIELDINFO_8BIT(info);
BYTES_VEC8BIT(list)
[(p - 1) / elts] =
SETELT_FIELDINFO_8BIT(info)[((p - 1) % elts) * 256 +
BYTES_VEC8BIT(list)[(p - 1) / elts]];
ResizeWordSizedBag(list, 3 * sizeof(UInt) + (p + elts - 2) / elts);
SET_LEN_VEC8BIT(list, p - 1);
} else {
PlainVec8Bit(list);
UNB_LIST(list, p);
} return0;
}
len = LEN_VEC8BIT(list);
info = GetFieldInfo8Bit(FIELD_VEC8BIT(list));
elts = ELS_BYTE_FIELDINFO_8BIT(info);
gettab = GETELT_FIELDINFO_8BIT(info);
nb = (len + elts - 1) / elts;
ptr = CONST_BYTES_VEC8BIT(list);
i = from / elts;
j = from % elts; // might be an initial part byte if (j) { if (i < nb && ptr[i]) for (j = from % elts; j < elts && (i * elts + j < len); j++) if (gettab[256 * j + ptr[i]] != 0) return elts * i + j + 1;
i++;
}
// skip empty bytes while (i < nb && !ptr[i])
i++;
if (i >= nb) return len + 1;
// Found a non-empty byte, locate the entry
byte = ptr[i];
j = 0; while (gettab[byte + 256 * j] == 0)
j++; return elts * i + j + 1;
}
len = LEN_VEC8BIT(vec);
l2 = LEN_PLIST(mat);
q = FIELD_VEC8BIT(vec);
// Get the first row, to establish the size of the result
row1 = ELM_PLIST(mat, 1); if (!IS_VEC8BIT_REP(row1) || FIELD_VEC8BIT(row1) != q) return TRY_NEXT_METHOD;
len1 = LEN_VEC8BIT(row1);
// create the result space
res = ZeroVec8Bit(q, len1, IS_MUTABLE_OBJ(vec) || IS_MUTABLE_OBJ(row1));
// Finally, we start work
info = GetFieldInfo8Bit(q);
elts = ELS_BYTE_FIELDINFO_8BIT(info);
gettab = GETELT_FIELDINFO_8BIT(info);
ffefelt = CONST_FFE_FELT_FIELDINFO_8BIT(info);
for (i = 0; i < len; i++) if (i < l2) {
x = ffefelt[gettab[CONST_BYTES_VEC8BIT(vec)[i / elts] + 256 * (i % elts)]]; if (VAL_FFE(x) != 0) {
row1 = ELM_PLIST(mat, i + 1); // This may be unduly draconian. Later we may want to be able // to promote the rows to a bigger field if ((!IS_VEC8BIT_REP(row1)) || (FIELD_VEC8BIT(row1) != q)) return TRY_NEXT_METHOD;
AddVec8BitVec8BitMultInner(res, res, row1, x, 1, len1);
}
} return res;
}
UInt iq = GetPositiveSmallInt(SELF_NAME, q);
PLAIN_LIST(list);
len = LEN_PLIST(list);
mut = IS_MUTABLE_OBJ(list);
GROW_PLIST(list, len + 1); for (i = len; i >= 1; i--) {
tmp = ELM_PLIST(list, i); if (!IS_VEC8BIT_REP(tmp)) {
ErrorMayQuit("CONV_MAT8BIT: argument must be a list of " "compressed 8bit vectors", 0, 0);
}
type = TypeVec8BitLocked(iq, IS_MUTABLE_OBJ(tmp));
SetTypeDatObj(tmp, type);
SET_ELM_MAT8BIT(list, i, tmp);
CHANGED_BAG(list);
}
SET_LEN_MAT8BIT(list, len);
RetypeBag(list, T_POSOBJ);
type = TypeMat8Bit(iq, mut);
SET_TYPE_POSOBJ(list, type); return0;
}
prod = NewWordSizedBag(T_POSOBJ, sizeof(Obj) * (len + 2));
SET_LEN_MAT8BIT(prod, len);
type = TypeMat8Bit(q, IS_MUTABLE_OBJ(matl) || IS_MUTABLE_OBJ(matr));
SET_TYPE_POSOBJ(prod, type);
locked_type = TypeVec8BitLocked(
q, IS_MUTABLE_OBJ(ELM_MAT8BIT(matl, 1)) // FIXME(0xn)
|| IS_MUTABLE_OBJ(ELM_MAT8BIT(matr, 1))); for (i = 1; i <= len; i++) {
row = ProdVec8BitMat8Bit(ELM_MAT8BIT(matl, i), matr);
// Since I'm going to put this vector into a matrix, I must lock its // representation, so that it doesn't get rewritten over GF(q^k)
SetTypeDatObj(row, locked_type);
SET_ELM_MAT8BIT(prod, i, row);
CHANGED_BAG(prod);
TakeInterrupt();
} return prod;
}
// set up cmat and inv. Note that the row numbering is offset
cmat = NEW_PLIST(T_PLIST, len);
zero = ZeroVec8Bit(q, len, 1);
o = FELT_FFE_FIELDINFO_8BIT(info)[1]; for (i = 1; i <= len; i++) {
row = ELM_MAT8BIT(mat, i);
row = SHALLOW_COPY_OBJ(row);
SET_ELM_PLIST(cmat, i, row);
CHANGED_BAG(cmat);
row = SHALLOW_COPY_OBJ(zero);
ptr = BYTES_VEC8BIT(row) + (i - 1) / elts;
// we can't retain this pointer, because of garbage collections
settab = SETELT_FIELDINFO_8BIT(info); // we know we are replacing a zero
*ptr = settab[256 * ((i - 1) % elts + o * elts)];
SET_ELM_PLIST(inv, i + 1, row);
CHANGED_BAG(inv);
}
// Now do Gaussian elimination in cmat and mirror it on inv // from here, no garbage collections are allowed until the end
gettab = GETELT_FIELDINFO_8BIT(info);
ffefelt = CONST_FFE_FELT_FIELDINFO_8BIT(info);
for (i = 1; i <= len; i++) {
off = (i - 1) / elts;
pos = (i - 1) % elts; // find a non-zero entry in column i for (j = i; j <= len; j++) {
row = ELM_PLIST(cmat, j);
byte = CONST_BYTES_VEC8BIT(row)[off]; if (byte != 0 && (x = gettab[byte + 256 * pos]) != 0) break;
}
// if we didn't find one if (j > len) return Fail;
// swap and normalize
row1 = ELM_PLIST(inv, j + 1); if (i != j) {
SET_ELM_PLIST(cmat, j, ELM_PLIST(cmat, i));
SET_ELM_PLIST(cmat, i, row);
SET_ELM_PLIST(inv, j + 1, ELM_PLIST(inv, i + 1));
SET_ELM_PLIST(inv, i + 1, row1);
} if (x != o) {
xi = INV(ffefelt[x]);
MultVec8BitFFEInner(row, row, xi, i, len);
MultVec8BitFFEInner(row1, row1, xi, 1, len);
}
// Now clean out column for (k = 1; k <= len; k++) { if (k < i || k > j) {
row2 = ELM_PLIST(cmat, k);
byte = CONST_BYTES_VEC8BIT(row2)[off]; if (byte != 0 && (x = gettab[byte + 256 * pos]) != 0) {
xn = AINV_SAMEMUT(ffefelt[x]);
AddVec8BitVec8BitMultInner(row2, row2, row, xn, i, len);
row2 = ELM_PLIST(inv, k + 1);
AddVec8BitVec8BitMultInner(row2, row2, row1, xn, 1, len);
}
}
} if (TakeInterrupt()) {
gettab = GETELT_FIELDINFO_8BIT(info);
ffefelt = CONST_FFE_FELT_FIELDINFO_8BIT(info);
}
}
// Now clean up inv and return it
SET_ELM_PLIST(inv, 1, INTOBJ_INT(len));
type = TypeVec8BitLocked(
q, mut == 2 || (mut == 1 && IS_MUTABLE_OBJ(ELM_MAT8BIT(mat, 1)))); for (i = 2; i <= len + 1; i++) {
row = ELM_PLIST(inv, i);
SetTypeDatObj(row, type);
}
RetypeBag(inv, T_POSOBJ);
type = TypeMat8Bit(q, mut == 2 || (mut == 1 && IS_MUTABLE_OBJ(mat)));
SET_TYPE_POSOBJ(inv, type);
CHANGED_BAG(inv); return inv;
}
if (LEN_MAT8BIT(mat) != LEN_VEC8BIT(ELM_MAT8BIT(mat, 1))) {
ErrorMayQuit("InverseOp: matrix must be square, not %d by %d",
LEN_MAT8BIT(mat), LEN_VEC8BIT(ELM_MAT8BIT(mat, 1)));
}
UInt r1 = GetSmallInt(SELF_NAME, row1);
UInt r2 = GetSmallInt(SELF_NAME, row2);
UInt m = LEN_MAT8BIT(mat); if (m < r1) {
ErrorMayQuit("row index %d exceeds %d, the number of rows", r1, m);
} if (m < r2) {
ErrorMayQuit("row index %d exceeds %d, the number of rows", r2, m);
}
Obj a = ELM_MAT8BIT(mat, r1);
Obj b = ELM_MAT8BIT(mat, r2);
UInt n = LEN_VEC8BIT(ELM_MAT8BIT(mat, 1)); if (n < c1) {
ErrorMayQuit("column index %d exceeds %d, the number of columns", c1, n);
} if (n < c2) {
ErrorMayQuit("column index %d exceeds %d, the number of columns", c2, n);
}
for (UInt i = 1; i <= m; ++i) {
Obj vec = ELM_MAT8BIT(mat, i); if (!IS_MUTABLE_OBJ(vec)) {
ErrorMayQuit("row %d is immutable", i, 0);
} if (LEN_VEC8BIT(vec) != n) {
ErrorMayQuit("row length mismatch, %d versus %d", n, LEN_VEC8BIT(vec));
}
Obj a = FuncELM_VEC8BIT(self, vec, col1);
Obj b = FuncELM_VEC8BIT(self, vec, col2); if (a != b) {
ASS_VEC8BIT(vec, col1, b);
ASS_VEC8BIT(vec, col2, a);
}
}
// handle last byte specially, unless it happens to be full if (len % elts != 0) {
gettab = GETELT_FIELDINFO_8BIT(info) + *ptr; for (i = len % elts - 1; i >= 0; i--) { if (gettab[256 * i] != 0) return (elts * (len / elts) + i + 1);
}
ptr--;
}
// now skip over empty bytes while (ptr >= ptrS && *ptr == 0)
ptr--; if (ptr < ptrS) return0;
// Now look in the rightmost non-empty byte for the position
gettab = GETELT_FIELDINFO_8BIT(info) + *ptr; for (i = elts - 1; i >= 0; i--) { if (gettab[256 * i] != 0) return (elts * (ptr - ptrS) + i + 1);
}
Panic("this should never happen");
}
if (True == DoFilter(IsLockedRepresentationVector, vec)) {
ErrorReturnVoid("Resize of locked compressed vector is forbidden", 0, 0, "You can `return;' to ignore the operation"); return;
}
q = FIELD_VEC8BIT(vec);
info = GetFieldInfo8Bit(q);
elts = ELS_BYTE_FIELDINFO_8BIT(info);
SET_LEN_VEC8BIT(vec, newlen);
ResizeWordSizedBag(vec, SIZE_VEC8BIT(newlen, elts)); // vector has got shorter. if (len > newlen) { if (newlen % elts) { // clean spare entries in last byte
settab = SETELT_FIELDINFO_8BIT(info);
byte = CONST_BYTES_VEC8BIT(vec)[(newlen - 1) / elts]; for (i = newlen % elts; i < elts; i++)
byte = settab[byte + 256 * i];
BYTES_VEC8BIT(vec)[(newlen - 1) / elts] = byte;
} // Clean spare bytes in last word for characteristic 2 if ((q % 2) == 0) for (i = (newlen + elts - 1) / elts; i % sizeof(UInt); i++)
BYTES_VEC8BIT(vec)[i] = 0;
}
// vector has got longer and might be dirty if (!knownclean && newlen > len) {
settab = SETELT_FIELDINFO_8BIT(info);
ptr = BYTES_VEC8BIT(vec); if (len) {
ptr += (len - 1) / elts;
byte = *ptr; for (i = (len - 1) % elts + 1; i < elts; i++)
byte = settab[byte + 256 * i];
*ptr++ = byte;
}
ptr2 = BYTES_VEC8BIT(vec) + (newlen + elts - 1) / elts; while (ptr < ptr2)
*ptr++ = (UInt1)0;
}
}
// The easy case is just a shift by bytes if (amount % elts == 0) { while (ptr2 < end)
*ptr1++ = *ptr2++;
} else { // The general case
from = amount;
to = 0;
fbyte = *ptr2;
tbyte = 0;
gettab = GETELT_FIELDINFO_8BIT(info);
settab = SETELT_FIELDINFO_8BIT(info);
// The easy case is just a shift by bytes if (amount % elts == 0) {
end = BYTES_VEC8BIT(vec); while (ptr2 >= end)
*ptr1-- = *ptr2--; while (ptr1 >= end)
*ptr1-- = (UInt1)0;
} else { // The general case
from = len - 1;
to = len + amount - 1;
fbyte = *ptr2;
tbyte = 0;
gettab = GETELT_FIELDINFO_8BIT(info);
settab = SETELT_FIELDINFO_8BIT(info);
// find a common field
info = GetFieldInfo8Bit(q);
d = D_FIELDINFO_8BIT(info);
q1 = FIELD_VEC8BIT(vr);
info1 = GetFieldInfo8Bit(q1);
d1 = D_FIELDINFO_8BIT(info1);
d0 = LcmDegree(d, d1);
p = P_FIELDINFO_8BIT(info);
GAP_ASSERT(p == P_FIELDINFO_8BIT(info1));
q0 = 1; for (i = 0; i < d0; i++)
q0 *= p;
// if the exponent is bigger than 31, overflow changes the value to 0 if (d0 > 8 || q0 > 256) return TRY_NEXT_METHOD; if ((q0 > q &&
CALL_1ARGS(IsLockedRepresentationVector, vl) == True) ||
(q0 > q1 && CALL_1ARGS(IsLockedRepresentationVector, vr) == True)) return TRY_NEXT_METHOD;
RewriteVec8Bit(vl, q0);
RewriteVec8Bit(vr, q0);
q = q0;
}
RequireNonnegativeSmallInt(SELF_NAME, ll);
RequireNonnegativeSmallInt(SELF_NAME, lr);
ll1 = INT_INTOBJ(ll);
lr1 = INT_INTOBJ(lr); if (0 > ll1 || ll1 > LEN_VEC8BIT(vl))
ErrorQuit("ProdCoeffs: given length <ll> of left argt (%d) is " "negative or longer than the argt (%d)",
INT_INTOBJ(ll), LEN_VEC8BIT(vl)); if (0 > lr1 || lr1 > LEN_VEC8BIT(vr))
ErrorQuit("ProdCoeffs: given length <lr> of right argt (%d) is " "negative or longer than the argt (%d)",
INT_INTOBJ(lr), LEN_VEC8BIT(vr));
info = GetFieldInfo8Bit(q); if (ll1 == 0 && lr1 == 0)
lenp = 0; else
lenp = ll1 + lr1 - 1;
res = ZeroVec8Bit(q, lenp, 1);
ProdCoeffsVec8Bit(res, vl, ll1, vr, lr1);
last = RightMostNonZeroVec8Bit(res); if (last != lenp)
ResizeVec8Bit(res, last, 1); return res;
}
// normalize a copy of v in vn -- normalize means monic, and actual length // equal to length parameter
vn = CopyVec8Bit(v, 1);
ResizeVec8Bit(vn, len, 0);
len1 = (len == 0) ? 0 : RightMostNonZeroVec8Bit(vn); if (len1 == 0)
ErrorReturnVoid("Zero coefficient vector for reduction", 0, 0, "you can 'return;'"); if (len1 != len) {
ResizeVec8Bit(vn, len1, 1);
len = len1;
}
// Now we start to build up the result
shifts = NEW_PLIST_IMM(T_PLIST_TAB, elts + 2);
SET_ELM_PLIST(shifts, elts + 1, INTOBJ_INT(len));
SET_ELM_PLIST(shifts, elts + 2, xi);
SET_LEN_PLIST(shifts, elts + 2);
// vn can simply be stored in one place
SET_ELM_PLIST(shifts, (len - 1) % elts + 1, vn);
CHANGED_BAG(shifts);
if (elts > 1) { // fill the rest up with zero vectors of suitable lengths for (i = 1; i < elts; i++) {
ashift = ZeroVec8Bit(q, len + i, 0);
SET_ELM_PLIST(shifts, (len + i - 1) % elts + 1, ashift);
CHANGED_BAG(shifts);
}
// reload the tables, in case there was a garbage collection
gettab = GETELT_FIELDINFO_8BIT(info);
settab = SETELT_FIELDINFO_8BIT(info); // Now run through the entries of vn inserting them into the shifted // versions
ptr = BYTES_VEC8BIT(vn); for (j = 1; j < elts; j++)
ptrs[j] =
BYTES_VEC8BIT(ELM_PLIST(shifts, (len + j - 1) % elts + 1)); for (i = 0; i < len; i++) {
x = gettab[*ptr + 256 * (i % elts)]; if (x != 0) { for (j = 1; j < elts; j++) {
*(ptrs[j]) = settab[*(ptrs[j]) + 256 * ((i + j) % elts + elts * x)];
}
} if (i % elts == elts - 1)
ptr++; else
ptrs[elts - 1 - (i % elts)]++;
}
} #ifdef HPCGAP for (i = 1; i <= elts; i++)
MakeBagReadOnly(ELM_PLIST(shifts, i));
MakeBagReadOnly(shifts); #endif return shifts;
}
q = FIELD_VEC8BIT(vl); if (q != FIELD_VEC8BIT(ELM_PLIST(vrshifted, 1))) return Fail;
RequireNonnegativeSmallInt(SELF_NAME, ll); if (INT_INTOBJ(ll) > LEN_VEC8BIT(vl)) {
ErrorQuit("QuotRemCoeffs: given length <ll> of left argt (%d) is " "longer than the argt (%d)",
INT_INTOBJ(ll), LEN_VEC8BIT(vl));
}
ill = INT_INTOBJ(ll);
rem = CopyVec8Bit(vl, 1);
info = GetFieldInfo8Bit(q);
ResizeVec8Bit(rem, ill, 0);
elts = ELS_BYTE_FIELDINFO_8BIT(info);
lr = INT_INTOBJ(ELM_PLIST(vrshifted, elts + 1));
quot = NewWordSizedBag(T_DATOBJ, SIZE_VEC8BIT(ill - lr + 1, elts));
type = TypeVec8Bit(q, 1);
SetTypeDatObj(quot, type);
SET_FIELD_VEC8BIT(quot, q);
SET_LEN_VEC8BIT(quot, ill - lr + 1);
ReduceCoeffsVec8Bit(rem, vrshifted, quot);
ret = NEW_PLIST(T_PLIST_TAB, 2);
SET_LEN_PLIST(ret, 2);
SET_ELM_PLIST(ret, 1, quot);
SET_ELM_PLIST(ret, 2, rem);
CHANGED_BAG(ret); return ret;
}
// Find the field info
q = FIELD_VEC8BIT(ELM_PLIST(mat, 1));
info = GetFieldInfo8Bit(q);
elts = ELS_BYTE_FIELDINFO_8BIT(info);
// Get the Felt numbers for zero and one
convtab = FELT_FFE_FIELDINFO_8BIT(info);
zero = convtab[0];
one = convtab[1];
// Set up the lists for the results
heads = NEW_PLIST(T_PLIST_CYC, ncols);
SET_LEN_PLIST(heads, ncols);
vectors = NEW_PLIST(T_PLIST_TAB_RECT, nrows);
nvecs = 0; if (TransformationsNeeded) {
coeffs = NEW_PLIST(T_PLIST_TAB_RECT, nrows);
relns = NEW_PLIST(T_PLIST_TAB_RECT, nrows);
nrels = 0;
} for (i = 1; i <= ncols; i++)
SET_ELM_PLIST(heads, i, INTOBJ_INT(0));
// Main loop starts here for (i = 1; i <= nrows; i++) {
row = ELM_PLIST(mat, i); if (TransformationsNeeded) {
coeffrow = NewWordSizedBag(T_DATOBJ, SIZE_VEC8BIT(nrows, elts));
SET_LEN_VEC8BIT(coeffrow, nrows);
type = TypeVec8Bit(q, 1);
SetTypeDatObj(coeffrow, type);
SET_FIELD_VEC8BIT(coeffrow, q);
CHANGED_BAG(coeffrow);
// No garbage collection risk from here
settab = SETELT_FIELDINFO_8BIT(info);
BYTES_VEC8BIT(coeffrow)
[(i - 1) / elts] = settab[256 * ((i - 1) % elts + elts * one)];
} // No garbage collection risk from here
gettab = GETELT_FIELDINFO_8BIT(info);
convtab1 = CONST_FFE_FELT_FIELDINFO_8BIT(info);
// Clear out the current row for (j = 1; j <= ncols; j++) {
h = INT_INTOBJ(ELM_PLIST(heads, j)); if (h != 0) {
byte = CONST_BYTES_VEC8BIT(row)[(j - 1) / elts]; if (byte &&
zero != (x = gettab[byte + 256 * ((j - 1) % elts)])) {
y = AINV_SAMEMUT(convtab1[x]);
AddVec8BitVec8BitMultInner(
row, row, ELM_PLIST(vectors, h), y, 1, ncols); if (TransformationsNeeded)
AddVec8BitVec8BitMultInner(coeffrow, coeffrow,
ELM_PLIST(coeffs, h), y, 1,
nrows);
}
}
}
j = 1;
rowp = CONST_BYTES_VEC8BIT(row); while (j <= ncols && !*rowp) {
j += elts;
rowp++;
} while (j <= ncols &&
(zero == (x = gettab[*rowp + 256 * ((j - 1) % elts)])))
j++;
if (j <= ncols) {
y = INV(convtab1[x]);
MultVec8BitFFEInner(row, row, y, 1, ncols);
SET_ELM_PLIST(vectors, ++nvecs, row);
CHANGED_BAG(vectors);
SET_LEN_PLIST(vectors, nvecs);
SET_ELM_PLIST(heads, j, INTOBJ_INT(nvecs)); if (TransformationsNeeded) {
MultVec8BitFFEInner(coeffrow, coeffrow, y, 1, nrows);
SET_ELM_PLIST(coeffs, nvecs, coeffrow);
CHANGED_BAG(coeffs);
SET_LEN_PLIST(coeffs, nvecs);
} // garbage collection OK again after here
} elseif (TransformationsNeeded) {
SET_ELM_PLIST(relns, ++nrels, coeffrow);
CHANGED_BAG(relns);
SET_LEN_PLIST(relns, nrels);
}
TakeInterrupt();
} if (RNheads == 0) {
RNheads = RNamName("heads");
RNvectors = RNamName("vectors");
}
res = NEW_PREC(TransformationsNeeded ? 4 : 2);
AssPRec(res, RNheads, heads);
AssPRec(res, RNvectors, vectors); if (LEN_PLIST(vectors) == 0)
RetypeBag(vectors, T_PLIST_EMPTY); if (TransformationsNeeded) { if (RNcoeffs == 0) {
RNcoeffs = RNamName("coeffs");
RNrelns = RNamName("relations");
}
AssPRec(res, RNcoeffs, coeffs); if (LEN_PLIST(coeffs) == 0)
RetypeBag(coeffs, T_PLIST_EMPTY);
AssPRec(res, RNrelns, relns); if (LEN_PLIST(relns) == 0)
RetypeBag(relns, T_PLIST_EMPTY);
}
SortPRecRNam(res); return res;
}
// set entries // run over elts row chunks of the original matrix for (i = 1; i <= l; i += elts) {
imod = (i - 1) / elts;
// run through these rows in chunks, extract the bytes corresponding // to an elts x elts submatrix into vals for (n = 0; n < nrb; n++) { for (j = 0; j < elts; j++) { if ((i + j) > l) {
if (LEN_MAT8BIT(mat) < r) {
ErrorMayQuit("row index %d exceeds %d, the number of rows", r,
LEN_MAT8BIT(mat));
}
Obj vec = ELM_MAT8BIT(mat, r); if (!IS_MUTABLE_OBJ(vec)) {
ErrorMayQuit("row %d is immutable", r, 0);
} if (LEN_VEC8BIT(vec) < c) {
ErrorMayQuit("column index %d exceeds %d, the number of columns", c,
LEN_VEC8BIT(vec));
}
// TODO: replace the following call by direct access? E.g. so that we can // always reject input elements in the "wrong domain"?
ASS_VEC8BIT(vec, col, elm); return0;
}
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.